feature/IO-3701-Harness-Replacement - Implement
This commit is contained in:
166
client/src/feature-flags/splitio-react-replacement.test.jsx
Normal file
166
client/src/feature-flags/splitio-react-replacement.test.jsx
Normal file
@@ -0,0 +1,166 @@
|
||||
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);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user