From 3d86605aaf00a21df97641e1314db4110ea446cd Mon Sep 17 00:00:00 2001 From: Teetow Date: Tue, 28 Apr 2026 07:12:34 +0200 Subject: [PATCH] test(promos): add unit tests for isPromoDateActive date range logic Make today injectable via optional parameter for deterministic testing. --- src/assets/data/promos/types.test.ts | 81 ++++++++++++++++++++++++++++ src/assets/data/promos/types.ts | 6 ++- 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 src/assets/data/promos/types.test.ts diff --git a/src/assets/data/promos/types.test.ts b/src/assets/data/promos/types.test.ts new file mode 100644 index 0000000..6a4bf9f --- /dev/null +++ b/src/assets/data/promos/types.test.ts @@ -0,0 +1,81 @@ +import { describe, expect, test } from "bun:test"; +import { isPromoDateActive } from "./types"; +import type { PromoData } from "./types"; + +const makePromo = (overrides: Partial = {}): PromoData => ({ + type: "banner", + message: "Test promo", + ...overrides, +}); + +describe("isPromoDateActive", () => { + describe("no date range set", () => { + test("returns true when neither startDate nor endDate is set", () => { + expect(isPromoDateActive(makePromo(), "2026-04-28")).toBe(true); + }); + }); + + describe("startDate only", () => { + test("returns false before startDate", () => { + expect( + isPromoDateActive(makePromo({ startDate: "2026-04-29" }), "2026-04-28"), + ).toBe(false); + }); + + test("returns true on startDate", () => { + expect( + isPromoDateActive(makePromo({ startDate: "2026-04-29" }), "2026-04-29"), + ).toBe(true); + }); + + test("returns true after startDate", () => { + expect( + isPromoDateActive(makePromo({ startDate: "2026-04-29" }), "2026-05-01"), + ).toBe(true); + }); + }); + + describe("endDate only", () => { + test("returns true before endDate", () => { + expect( + isPromoDateActive(makePromo({ endDate: "2026-05-13" }), "2026-05-12"), + ).toBe(true); + }); + + test("returns true on endDate", () => { + expect( + isPromoDateActive(makePromo({ endDate: "2026-05-13" }), "2026-05-13"), + ).toBe(true); + }); + + test("returns false after endDate", () => { + expect( + isPromoDateActive(makePromo({ endDate: "2026-05-13" }), "2026-05-14"), + ).toBe(false); + }); + }); + + describe("startDate and endDate", () => { + const promo = makePromo({ startDate: "2026-04-29", endDate: "2026-05-13" }); + + test("returns false before window", () => { + expect(isPromoDateActive(promo, "2026-04-28")).toBe(false); + }); + + test("returns true on first day", () => { + expect(isPromoDateActive(promo, "2026-04-29")).toBe(true); + }); + + test("returns true mid-window", () => { + expect(isPromoDateActive(promo, "2026-05-06")).toBe(true); + }); + + test("returns true on last day", () => { + expect(isPromoDateActive(promo, "2026-05-13")).toBe(true); + }); + + test("returns false after window", () => { + expect(isPromoDateActive(promo, "2026-05-14")).toBe(false); + }); + }); +}); diff --git a/src/assets/data/promos/types.ts b/src/assets/data/promos/types.ts index e23af86..b56003a 100644 --- a/src/assets/data/promos/types.ts +++ b/src/assets/data/promos/types.ts @@ -66,8 +66,10 @@ const routeMatchesAllowlist = (path: string, allowlist: string[]) => allowlist.some((route) => path === route || path.startsWith(`${route}/`)); /** Returns false if today is outside the promo's startDate/endDate window. */ -export const isPromoDateActive = (promo: PromoData): boolean => { - const today = new Date().toISOString().slice(0, 10); +export const isPromoDateActive = ( + promo: PromoData, + today = new Date().toISOString().slice(0, 10), +): boolean => { if (promo.startDate && today < promo.startDate) return false; if (promo.endDate && today > promo.endDate) return false; return true;