unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
247 lines • 9.25 kB
JavaScript
import { DeltaCache } from './delta-cache.js';
import { DELTA_EVENT_TYPES, } from './client-feature-toggle-delta-types.js';
describe('RevisionCache', () => {
it('should not create a synthetic base event when hydration has no features', () => {
const deltaCache = new DeltaCache({
eventId: 0,
features: [],
type: 'hydration',
segments: [],
}, 2);
expect(deltaCache.getEvents()).toEqual([]);
expect(deltaCache.getHydrationEvent()).toEqual({
eventId: 0,
features: [],
type: 'hydration',
segments: [],
});
});
it('should always update the hydration event and remove event when over limit', () => {
const baseEvent = {
eventId: 1,
features: [
{
name: 'test-flag',
type: 'release',
enabled: false,
project: 'default',
stale: false,
strategies: [
{
name: 'flexibleRollout',
constraints: [],
parameters: {
groupId: 'test-flag',
rollout: '100',
stickiness: 'default',
},
variants: [],
},
],
variants: [],
description: null,
impressionData: false,
},
{
name: 'my-feature-flag',
type: 'release',
enabled: true,
project: 'default',
stale: false,
strategies: [
{
name: 'flexibleRollout',
constraints: [],
parameters: {
groupId: 'my-feature-flag',
rollout: '100',
stickiness: 'default',
},
variants: [],
},
],
variants: [],
description: null,
impressionData: false,
},
],
type: 'hydration',
segments: [
{
id: 1,
name: 'update-segment',
constraints: [],
},
{
id: 2,
name: 'remove-segment',
constraints: [],
},
],
};
const initialEvents = [
{
eventId: 2,
feature: {
name: 'my-feature-flag',
type: 'release',
enabled: true,
project: 'default',
stale: false,
strategies: [
{
name: 'flexibleRollout',
constraints: [],
parameters: {
groupId: 'my-feature-flag',
rollout: '100',
stickiness: 'default',
},
variants: [],
},
],
variants: [],
description: null,
impressionData: false,
},
type: DELTA_EVENT_TYPES.FEATURE_UPDATED,
},
];
const maxLength = 2;
const deltaCache = new DeltaCache(baseEvent, maxLength);
deltaCache.addEvents(initialEvents);
// Add a new revision to trigger changeBase
const addedEvents = [
{
eventId: 3,
type: DELTA_EVENT_TYPES.FEATURE_UPDATED,
feature: {
name: 'another-feature-flag',
type: 'release',
enabled: true,
project: 'default',
stale: false,
strategies: [
{
name: 'flexibleRollout',
constraints: [],
parameters: {
groupId: 'another-feature-flag',
rollout: '100',
stickiness: 'default',
},
},
],
variants: [],
description: null,
impressionData: false,
},
},
{
eventId: 4,
type: DELTA_EVENT_TYPES.FEATURE_REMOVED,
featureName: 'test-flag',
project: 'default',
},
{
eventId: 5,
type: DELTA_EVENT_TYPES.SEGMENT_UPDATED,
segment: {
id: 1,
name: 'update-segment-new',
constraints: [],
},
},
{
eventId: 6,
type: DELTA_EVENT_TYPES.SEGMENT_REMOVED,
segmentId: 2,
},
{
eventId: 7,
type: DELTA_EVENT_TYPES.SEGMENT_UPDATED,
segment: {
id: 3,
name: 'new-segment',
constraints: [],
},
},
];
deltaCache.addEvents(addedEvents);
const events = deltaCache.getEvents();
// Check that the base has been changed and merged correctly
expect(events.length).toBe(maxLength);
expect(events).toEqual(addedEvents.slice(-2));
const hydrationEvent = deltaCache.getHydrationEvent();
expect(hydrationEvent.features).toHaveLength(2);
expect(hydrationEvent.eventId).toEqual(7);
expect(hydrationEvent.features).toEqual(expect.arrayContaining([
expect.objectContaining({ name: 'my-feature-flag' }),
expect.objectContaining({ name: 'another-feature-flag' }),
]));
expect(hydrationEvent.segments).toEqual(expect.arrayContaining([
expect.objectContaining({ name: 'update-segment-new', id: 1 }),
expect.objectContaining({ name: 'new-segment' }),
]));
});
it('should not mutate previous feature-updated events when new events with the same feature name are added', () => {
const baseEvent = {
eventId: 1,
features: [
{
name: 'base-flag',
type: 'release',
enabled: true,
project: 'streaming-deltas',
stale: false,
strategies: [],
variants: [],
description: null,
impressionData: false,
},
],
type: 'hydration',
segments: [],
};
const deltaCache = new DeltaCache(baseEvent, 10);
const initialFeatureEvent = {
eventId: 129,
type: DELTA_EVENT_TYPES.FEATURE_UPDATED,
feature: {
impressionData: false,
enabled: false,
name: 'streaming-test',
description: null,
project: 'streaming-deltas',
stale: false,
type: 'release',
variants: [],
strategies: [],
},
};
// This tests is to verify that the initialFeatureEvent is not mutated when a new event with the same feature name is added
// the following dirty way to clone this object is to avoid mutation on the comparison object. Because the object is passed by reference
// we would be comparing the same object with itself which would cause the expect check to always pass because the comparison would
// also change to match the object being compared.
deltaCache.addEvents([JSON.parse(JSON.stringify(initialFeatureEvent))]);
const updatedFeatureEvent = {
eventId: 130,
type: DELTA_EVENT_TYPES.FEATURE_UPDATED,
feature: {
impressionData: false,
enabled: true,
name: 'streaming-test',
description: null,
project: 'streaming-deltas',
stale: false,
type: 'release',
variants: [],
strategies: [{ name: 'new-strategy', parameters: {} }],
},
};
deltaCache.addEvents([updatedFeatureEvent]);
// @ts-expect-error
expect(deltaCache.events[1]).toStrictEqual(initialFeatureEvent);
});
});
//# sourceMappingURL=delta-cache.test.js.map