unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
184 lines • 7.02 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const database_init_1 = __importDefault(require("../../../test/e2e/helpers/database-init"));
const test_helper_1 = require("../../../test/e2e/helpers/test-helper");
const no_logger_1 = __importDefault(require("../../../test/fixtures/no-logger"));
const types_1 = require("../../types");
const feature_lifecycle_read_model_1 = require("./feature-lifecycle-read-model");
const metric_events_1 = require("../../metric-events");
let app;
let db;
let featureLifecycleStore;
let eventStore;
let eventBus;
let featureLifecycleReadModel;
beforeAll(async () => {
db = await (0, database_init_1.default)('feature_lifecycle', no_logger_1.default, {
dbInitMethod: 'legacy',
});
app = await (0, test_helper_1.setupAppWithAuth)(db.stores, {
experimental: {
flags: {},
},
}, db.rawDatabase);
eventStore = db.stores.eventStore;
eventBus = app.config.eventBus;
featureLifecycleReadModel = new feature_lifecycle_read_model_1.FeatureLifecycleReadModel(db.rawDatabase, app.config.flagResolver);
featureLifecycleStore = db.stores.featureLifecycleStore;
await app.request
.post(`/auth/demo/login`)
.send({
email: 'user@getunleash.io',
})
.expect(200);
});
afterAll(async () => {
await app.destroy();
await db.destroy();
});
beforeEach(async () => {
await featureLifecycleStore.deleteAll();
});
const getFeatureLifecycle = async (featureName, expectedCode = 200) => {
return app.request
.get(`/api/admin/projects/default/features/${featureName}/lifecycle`)
.expect(expectedCode);
};
const getCurrentStage = async (featureName) => {
return featureLifecycleReadModel.findCurrentStage(featureName);
};
const completeFeature = async (featureName, status, expectedCode = 200) => {
return app.request
.post(`/api/admin/projects/default/features/${featureName}/lifecycle/complete`)
.send(status)
.expect(expectedCode);
};
const uncompleteFeature = async (featureName, expectedCode = 200) => {
return app.request
.post(`/api/admin/projects/default/features/${featureName}/lifecycle/uncomplete`)
.expect(expectedCode);
};
function reachedStage(feature, stage) {
return new Promise((resolve) => eventBus.on(metric_events_1.STAGE_ENTERED, (event) => {
if (event.stage === stage && event.feature === feature)
resolve(stage);
}));
}
const expectFeatureStage = async (featureName, stage) => {
const { body: feature } = await app.getProjectFeatures('default', featureName);
expect(feature.lifecycle).toMatchObject({
stage,
enteredStageAt: expect.any(String),
});
};
test('should return lifecycle stages', async () => {
await app.createFeature('my_feature_a');
await app.enableFeature('my_feature_a', 'default');
eventStore.emit(types_1.FEATURE_CREATED, { featureName: 'my_feature_a' });
await reachedStage('my_feature_a', 'initial');
await expectFeatureStage('my_feature_a', 'initial');
eventBus.emit(types_1.CLIENT_METRICS_ADDED, [
{
featureName: 'my_feature_a',
environment: 'default',
},
{
featureName: 'non_existent_feature',
environment: 'default',
},
]);
// missing feature
eventBus.emit(types_1.CLIENT_METRICS_ADDED, [
{
environment: 'default',
yes: 0,
no: 0,
},
]);
// non existent env
eventBus.emit(types_1.CLIENT_METRICS_ADDED, [
{
featureName: 'my_feature_a',
environment: 'non-existent',
},
]);
await reachedStage('my_feature_a', 'live');
await expectFeatureStage('my_feature_a', 'live');
eventStore.emit(types_1.FEATURE_ARCHIVED, { featureName: 'my_feature_a' });
await reachedStage('my_feature_a', 'archived');
const { body } = await getFeatureLifecycle('my_feature_a');
expect(body).toEqual([
{
stage: 'initial',
enteredStageAt: expect.any(String),
},
{ stage: 'pre-live', enteredStageAt: expect.any(String) },
{
stage: 'live',
enteredStageAt: expect.any(String),
},
{
stage: 'archived',
enteredStageAt: expect.any(String),
},
]);
await expectFeatureStage('my_feature_a', 'archived');
eventStore.emit(types_1.FEATURE_REVIVED, { featureName: 'my_feature_a' });
await reachedStage('my_feature_a', 'initial');
});
test('should be able to toggle between completed/uncompleted', async () => {
await app.createFeature('my_feature_b');
await completeFeature('my_feature_b', {
status: 'kept',
statusValue: 'variant1',
});
const currentStage = await getCurrentStage('my_feature_b');
expect(currentStage).toMatchObject({ stage: 'completed', status: 'kept' });
await expectFeatureStage('my_feature_b', 'completed');
await uncompleteFeature('my_feature_b');
const { body } = await getFeatureLifecycle('my_feature_b');
expect(body).toEqual([]);
});
test('should backfill intialized feature', async () => {
await app.createFeature('my_feature_c');
await featureLifecycleStore.delete('my_feature_c');
await featureLifecycleStore.backfill();
const { body } = await getFeatureLifecycle('my_feature_c');
expect(body).toEqual([
{ stage: 'initial', enteredStageAt: expect.any(String) },
]);
});
test('should backfill archived feature', async () => {
await app.createFeature('my_feature_d');
await app.archiveFeature('my_feature_d');
await featureLifecycleStore.delete('my_feature_d');
await featureLifecycleStore.backfill();
const { body } = await getFeatureLifecycle('my_feature_d');
expect(body).toEqual([
{ stage: 'initial', enteredStageAt: expect.any(String) },
{ stage: 'archived', enteredStageAt: expect.any(String) },
]);
});
test('should not backfill for existing lifecycle', async () => {
await app.createFeature('my_feature_e');
await app.enableFeature('my_feature_e', 'default');
eventStore.emit(types_1.FEATURE_CREATED, { featureName: 'my_feature_e' });
eventBus.emit(types_1.CLIENT_METRICS_ADDED, [
{
featureName: 'my_feature_e',
environment: 'default',
},
]);
await reachedStage('my_feature_e', 'live');
await featureLifecycleStore.backfill();
const { body } = await getFeatureLifecycle('my_feature_e');
expect(body).toEqual([
{ stage: 'initial', enteredStageAt: expect.any(String) },
{ stage: 'pre-live', enteredStageAt: expect.any(String) },
{ stage: 'live', enteredStageAt: expect.any(String) },
]);
});
//# sourceMappingURL=feature-lifecycle.e2e.test.js.map