fix: Befunde aus Sicherheits- und Korrektheitsreview der Bienenpatenschaft
Docker Image bauen und veroeffentlichen / typecheck (push) Successful in 2m57s
Docker Image bauen und veroeffentlichen / lint (push) Successful in 3m7s
Docker Image bauen und veroeffentlichen / build-and-push (push) Canceled after 0s
Docker Image bauen und veroeffentlichen / test (push) Canceled after 1m22s
Docker Image bauen und veroeffentlichen / typecheck (push) Successful in 2m57s
Docker Image bauen und veroeffentlichen / lint (push) Successful in 3m7s
Docker Image bauen und veroeffentlichen / build-and-push (push) Canceled after 0s
Docker Image bauen und veroeffentlichen / test (push) Canceled after 1m22s
- Oeffentliche Kuendigung: exakte Identifikation, Limits je Vertrag und Adresse, Bestaetigung nur an die Kontoadresse mit Ruecknahme-Link (HMAC) - Vorschau: Body-Grenze beim Lesen, Parallelitaets- und Minutenlimit, Cache - Rabatte gelten nicht fuer Patenschaftspositionen - Abo aktiv erst nach bestaetigter Zahlung, offene Abschluesse zaehlen zum Kontingent und werden nach 24 h aufgeraeumt, Sitzung 58 Minuten - Konto-Loeschung nur ohne laufendes Abo, Urkunden-Dateien werden entfernt - Abo-Lieferungen mit Zahlungszeile (DHL-Marke moeglich) - Shop zeigt freien Bestand nach Abo-Reservierung - Storno/volle Erstattung widerruft die Patenschaft (Status WIDERRUFEN) - Umsatzsteuer der Patenschaft per VAT_RATE_PERCENT_PATENSCHAFT (19 %) - Digitale Bestellungen archivieren sich, Kalendertage in Europe/Berlin, Monatsenden begrenzt, Datenauskunft um Patenschaften ergaenzt Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
f227aeb8f9
commit
515fca1c16
97 files changed
+2979
-254
No files matched your search
@@ -5,6 +5,7 @@ const m = vi.hoisted(() => ({
|
||||
getCurrentCustomer: vi.fn(),
|
||||
getOfferBySlug: vi.fn(),
|
||||
createSubscriptionCheckout: vi.fn(),
|
||||
preparePendingCheckout: vi.fn(),
|
||||
isTrustedOrigin: vi.fn(),
|
||||
}));
|
||||
|
||||
@@ -14,6 +15,7 @@ vi.mock("@/lib/rate-limit", () => ({ rateLimit: () => true, getClientIp: async (
|
||||
vi.mock("@/i18n/locale", () => ({ getLocale: async () => "de" }));
|
||||
vi.mock("@/lib/sponsorship/offers", () => ({ getOfferBySlug: m.getOfferBySlug }));
|
||||
vi.mock("@/lib/sponsorship-subscription/checkout", () => ({ createSubscriptionCheckout: m.createSubscriptionCheckout }));
|
||||
vi.mock("@/lib/sponsorship-subscription/pending", () => ({ preparePendingCheckout: m.preparePendingCheckout }));
|
||||
vi.mock("@/lib/certificate/layout", () => ({ checkCertificateFits: () => ({ ok: true }) }));
|
||||
|
||||
const { POST } = await import("./route");
|
||||
@@ -38,6 +40,7 @@ beforeEach(() => {
|
||||
m.getCurrentCustomer.mockResolvedValue(CUSTOMER);
|
||||
m.getOfferBySlug.mockResolvedValue({ id: "offer_1", slug: "vierteljaehrlich", kind: "ABO", isAvailable: true });
|
||||
m.createSubscriptionCheckout.mockResolvedValue({ clientSecret: "cs_secret", subscriptionId: "sub_local" });
|
||||
m.preparePendingCheckout.mockResolvedValue({ ok: true });
|
||||
});
|
||||
|
||||
describe("POST /api/patenschaft/abo", () => {
|
||||
@@ -87,4 +90,21 @@ describe("POST /api/patenschaft/abo", () => {
|
||||
expect(response.status).toBe(502);
|
||||
expect(JSON.stringify(await response.json())).not.toContain("sk_test");
|
||||
});
|
||||
|
||||
test("bereitet den Abschluss vor (alter offener Abschluss desselben Angebots wird ersetzt)", async () => {
|
||||
await post({ offerSlug: "vierteljaehrlich", personalization: PERSONALIZATION });
|
||||
|
||||
expect(m.preparePendingCheckout).toHaveBeenCalledWith({ customerId: "cust_1", offerId: "offer_1" });
|
||||
expect(m.preparePendingCheckout.mock.invocationCallOrder[0]).toBeLessThan(m.createSubscriptionCheckout.mock.invocationCallOrder[0]);
|
||||
});
|
||||
|
||||
test("mehr als drei offene Abschluesse je Konto: klare Ablehnung, kein neuer Checkout", async () => {
|
||||
m.preparePendingCheckout.mockResolvedValue({ ok: false, reason: "too_many_pending" });
|
||||
|
||||
const response = await post({ offerSlug: "vierteljaehrlich", personalization: PERSONALIZATION });
|
||||
|
||||
expect(response.status).toBe(409);
|
||||
expect(await response.json()).toMatchObject({ code: "too_many_pending", error: expect.stringContaining("offene Abo-Abschlüsse") });
|
||||
expect(m.createSubscriptionCheckout).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user