Files
bodyshop/client/src/feature-flags/splitio-react-replacement.test.jsx

167 lines
5.1 KiB
JavaScript

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);
});
});