import { beforeEach, describe, expect, it, vi } from "vitest"; import { __featureFlagTesting } from "./splitio-react-replacement"; const { createFeatureFlagClient, getNextScheduleRefreshDelay, getLocalStorageKey, isFeatureFlagChangeRelevant, normalizeFlagValue, readCachedFeatureFlags, writeCachedFeatureFlags } = __featureFlagTesting; beforeEach(() => { window.localStorage.clear(); vi.useRealTimers(); }); describe("splitio-react-replacement feature flag normalization", () => { it("returns off for unknown or null values", () => { expect(normalizeFlagValue(null)).toEqual({ treatment: "off", config: null }); expect(normalizeFlagValue(undefined)).toEqual({ treatment: "off", config: null }); }); it("normalizes primitive values into Split-like treatments", () => { expect(normalizeFlagValue(true)).toEqual({ treatment: "on", config: null }); expect(normalizeFlagValue(false)).toEqual({ treatment: "off", config: null }); expect(normalizeFlagValue(1)).toEqual({ treatment: "on", config: null }); expect(normalizeFlagValue(0)).toEqual({ treatment: "off", config: null }); expect(normalizeFlagValue("true")).toEqual({ treatment: "on", config: null }); expect(normalizeFlagValue("false")).toEqual({ treatment: "off", config: null }); expect(normalizeFlagValue("variant-a")).toEqual({ treatment: "variant-a", config: null }); }); it("preserves custom treatments and parses JSON config strings", () => { expect( normalizeFlagValue({ treatment: "demo", config: "{\"limit\":25}" }) ).toEqual({ treatment: "demo", config: { limit: 25 } }); }); it("respects activeDate and deactiveDate windows", () => { vi.useFakeTimers(); vi.setSystemTime(new Date("2026-05-19T15:00:00.000Z")); expect( normalizeFlagValue({ treatment: "on", activeDate: "2026-05-19T14:59:00.000Z", deactiveDate: "2026-05-19T15:01:00.000Z" }) ).toEqual({ treatment: "on", config: null }); expect( normalizeFlagValue({ treatment: "on", activeDate: "2026-05-19T15:01:00.000Z" }) ).toEqual({ treatment: "off", config: null }); expect( normalizeFlagValue({ treatment: "on", deactiveDate: "2026-05-19T15:00:00.000Z" }) ).toEqual({ treatment: "off", config: null }); vi.useRealTimers(); }); }); describe("splitio-react-replacement feature flag client", () => { it("uses backend flags", () => { const client = createFeatureFlagClient({ bodyshop: { imexshopid: "APPLE" }, backendFlags: { Enhanced_Payroll: { treatment: "on" } } }); expect(client.getTreatment("Enhanced_Payroll")).toBe("on"); }); it("ignores old bodyshop feature JSON fallback values", () => { const client = createFeatureFlagClient({ bodyshop: { imexshopid: "APPLE", features: { featureFlags: { Enhanced_Payroll: { treatment: "on" } } } }, backendFlags: {} }); expect(client.getTreatment("Enhanced_Payroll")).toBe("off"); }); it("returns off for flags that are not present in any source", () => { const client = createFeatureFlagClient({ bodyshop: { imexshopid: "APPLE", features: {} }, backendFlags: {} }); expect(client.getTreatment("Missing_Flag")).toBe("off"); }); it("uses a bodyshop-scoped browser cache key", () => { expect(getLocalStorageKey("shop-1")).toBe("bodyshop-feature-flags:shop-1"); }); it("stores and reads last-known backend flags from browser storage", () => { vi.useFakeTimers(); vi.setSystemTime(new Date("2026-05-19T15:00:00.000Z")); writeCachedFeatureFlags("shop-1", { Enhanced_Payroll: { treatment: "on", config: null } }); expect(readCachedFeatureFlags("shop-1")).toEqual({ Enhanced_Payroll: { treatment: "on", config: null } }); }); it("ignores expired browser cached flags", () => { vi.useFakeTimers(); vi.setSystemTime(new Date("2026-05-19T15:00:00.000Z")); writeCachedFeatureFlags("shop-1", { Enhanced_Payroll: { treatment: "on", config: null } }); expect(readCachedFeatureFlags("shop-1", Date.parse("2026-05-20T15:00:01.000Z"))).toBeNull(); }); }); describe("splitio-react-replacement live refresh helpers", () => { it("matches global and bodyshop-scoped socket changes", () => { expect(isFeatureFlagChangeRelevant({ scope: "global" }, "shop-1")).toBe(true); expect(isFeatureFlagChangeRelevant({ bodyshopId: "shop-1", scope: "bodyshop" }, "shop-1")).toBe(true); expect(isFeatureFlagChangeRelevant({ bodyshopId: "shop-2", scope: "bodyshop" }, "shop-1")).toBe(false); }); it("finds the next active/deactive date boundary that needs a refresh", () => { const now = Date.parse("2026-05-19T15:00:00.000Z"); expect( getNextScheduleRefreshDelay( { Demo: { treatment: "on", activeDate: "2026-05-19T15:05:00.000Z" }, Expiring: { treatment: "on", deactiveDate: "2026-05-19T15:02:00.000Z" }, Expired: { treatment: "on", deactiveDate: "2026-05-19T14:59:00.000Z" } }, now ) ).toBe(120050); }); });