unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
229 lines • 9.92 kB
JavaScript
import dbInit from '../../../../test/e2e/helpers/database-init.js';
import getLogger from '../../../../test/fixtures/no-logger.js';
let stores;
let db;
let featureToggleStore;
let projectStore;
beforeAll(async () => {
getLogger.setMuteError(true);
db = await dbInit('feature_toggle_store_serial', getLogger);
stores = db.stores;
featureToggleStore = stores.featureToggleStore;
projectStore = stores.projectStore;
});
afterAll(async () => {
await db.destroy();
});
test('should not crash for unknown toggle', async () => {
const project = await featureToggleStore.getProjectId('missing-toggle-name');
expect(project).toBe(undefined);
});
test('should not crash for undefined toggle name', async () => {
const project = await featureToggleStore.getProjectId(undefined);
expect(project).toBe(undefined);
});
describe('potentially_stale marking', () => {
afterEach(async () => {
await featureToggleStore.deleteAll();
});
const getFutureTimestamp = (days) => {
return new Date(Date.now() +
days * 24 * 60 * 60 * 1000 +
// add an extra second
1000).toISOString();
};
test('it returns an empty list if no toggles were updated', async () => {
const features = [
{
name: 'feature1',
type: 'release',
createdByUserId: 9999,
},
];
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
const markedToggles = await featureToggleStore.updatePotentiallyStaleFeatures();
expect(markedToggles).toStrictEqual([]);
});
test('it returns only updated toggles', async () => {
const features = [
{
name: 'feature1',
type: 'release',
createdByUserId: 9999,
},
{
name: 'feature2',
type: 'kill-switch',
createdByUserId: 9999,
},
];
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
const markedToggles = await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(41));
expect(markedToggles).toStrictEqual([
{ name: 'feature1', potentiallyStale: true, project: 'default' },
]);
});
test.each([
[0, []],
[7, ['operational']],
[40, ['operational', 'release', 'experiment']],
[10000, ['operational', 'release', 'experiment']],
])('it marks toggles based on their type (days elapsed: %s)', async (daysElapsed, expectedMarkedFeatures) => {
const features = [
'release',
'experiment',
'operational',
'kill-switch',
'permission',
].map((type) => ({ name: type, type, createdByUserId: 9999 }));
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
for (const feature of expectedMarkedFeatures) {
expect(await featureToggleStore.get(feature)).toBeTruthy();
}
const markedToggles = await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(daysElapsed));
expect(markedToggles).toEqual(expect.arrayContaining(expectedMarkedFeatures.map((name) => ({
name,
potentiallyStale: true,
project: 'default',
}))));
expect(markedToggles.length).toEqual(expectedMarkedFeatures.length);
for (const feature of expectedMarkedFeatures) {
expect(await featureToggleStore.isPotentiallyStale(feature)).toBeTruthy();
}
});
test('it does not mark toggles already flagged as stale', async () => {
const features = [
{
name: 'feature1',
type: 'release',
stale: true,
createdByUserId: 9999,
},
];
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
const markedToggles = await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(1000));
expect(markedToggles).toStrictEqual([]);
});
test('it does not mark archived toggles potentially stale', async () => {
const features = [
{
name: 'feature1',
type: 'release',
archived: true,
createdByUserId: 9999,
},
];
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
const markedToggles = await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(1000));
expect(markedToggles).toStrictEqual([]);
});
test('it does not return toggles previously marked as potentially_stale', async () => {
const features = [
{
name: 'feature1',
type: 'release',
createdByUserId: 9999,
},
];
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
const markedToggles = await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(50));
expect(markedToggles).toStrictEqual([
{ name: 'feature1', potentiallyStale: true, project: 'default' },
]);
expect(await featureToggleStore.isPotentiallyStale('feature1')).toBeTruthy();
const secondPass = await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(100));
expect(secondPass).toStrictEqual([]);
});
describe('changing feature types', () => {
test("if a potentially stale feature changes to a type that shouldn't be stale, it's 'potentially_stale' marker is removed.", async () => {
const features = [
{
name: 'feature1',
type: 'release',
createdByUserId: 9999,
},
];
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
const markedToggles = await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(50));
expect(markedToggles).toStrictEqual([
{
name: 'feature1',
potentiallyStale: true,
project: 'default',
},
]);
expect(await featureToggleStore.isPotentiallyStale('feature1')).toBeTruthy();
await featureToggleStore.update('default', {
name: 'feature1',
type: 'kill-switch',
});
expect(await featureToggleStore.updatePotentiallyStaleFeatures()).toStrictEqual([
{
name: 'feature1',
potentiallyStale: false,
project: 'default',
},
]);
const potentiallyStale = await featureToggleStore.isPotentiallyStale('feature1');
expect(potentiallyStale).toBeFalsy();
});
test('if a fresh feature changes to a type that should be stale, it gets marked as potentially stale', async () => {
const features = [
{
name: 'feature1',
type: 'kill-switch',
createdByUserId: 9999,
},
];
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
const markedToggles = await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(50));
expect(markedToggles).toStrictEqual([]);
await featureToggleStore.update('default', {
name: 'feature1',
type: 'release',
});
await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(40));
const potentiallyStale = await featureToggleStore.isPotentiallyStale('feature1');
expect(potentiallyStale).toBeTruthy();
});
test('if a stale feature changes to a type that should be stale, it does not get marked as potentially stale', async () => {
const features = [
{
name: 'feature1',
type: 'kill-switch',
stale: true,
createdByUserId: 9999,
},
];
await Promise.all(features.map((feature) => featureToggleStore.create('default', feature)));
await featureToggleStore.update('default', {
name: 'feature1',
type: 'release',
});
await featureToggleStore.updatePotentiallyStaleFeatures(getFutureTimestamp(40));
const potentiallyStale = await featureToggleStore.isPotentiallyStale('feature1');
expect(potentiallyStale).toBeFalsy();
});
test('it should filter projects for playground', async () => {
await projectStore.create({
id: 'MyProject',
name: 'MyProject',
description: 'MyProject',
});
await featureToggleStore.create('default', {
name: 'featureA',
createdByUserId: 9999,
});
await featureToggleStore.create('MyProject', {
name: 'featureB',
createdByUserId: 9999,
});
const playgroundFeatures = await featureToggleStore.getPlaygroundFeatures({
project: ['MyProject'],
});
expect(playgroundFeatures).toHaveLength(1);
expect(playgroundFeatures[0].project).toBe('MyProject');
});
});
});
//# sourceMappingURL=feature-toggle-store.e2e.test.js.map