2021-08-12 15:04:37 +02:00
|
|
|
import createStores from '../../test/fixtures/store';
|
|
|
|
import getLogger from '../../test/fixtures/no-logger';
|
2019-03-13 19:10:13 +01:00
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
import StateService from './state-service';
|
|
|
|
import {
|
2019-03-13 19:10:13 +01:00
|
|
|
FEATURE_IMPORT,
|
|
|
|
DROP_FEATURES,
|
|
|
|
STRATEGY_IMPORT,
|
|
|
|
DROP_STRATEGIES,
|
2021-03-12 11:08:10 +01:00
|
|
|
TAG_TYPE_IMPORT,
|
|
|
|
TAG_IMPORT,
|
|
|
|
PROJECT_IMPORT,
|
2021-08-12 15:04:37 +02:00
|
|
|
} from '../types/events';
|
2021-09-24 08:55:53 +02:00
|
|
|
import { GLOBAL_ENV } from '../types/environment';
|
2019-03-13 19:10:13 +01:00
|
|
|
|
2021-07-07 10:46:50 +02:00
|
|
|
const oldExportExample = require('./state-service-export-v1.json');
|
|
|
|
|
2019-03-13 19:10:13 +01:00
|
|
|
function getSetup() {
|
2021-08-12 15:04:37 +02:00
|
|
|
const stores = createStores();
|
2020-09-28 21:54:44 +02:00
|
|
|
return {
|
|
|
|
stateService: new StateService(stores, { getLogger }),
|
|
|
|
stores,
|
|
|
|
};
|
2019-03-13 19:10:13 +01:00
|
|
|
}
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should import a feature', async () => {
|
2019-03-13 19:10:13 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
features: [
|
|
|
|
{
|
|
|
|
name: 'new-feature',
|
|
|
|
enabled: true,
|
|
|
|
strategies: [{ name: 'default' }],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
await stateService.import({ data });
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(1);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(events[0].type).toBe(FEATURE_IMPORT);
|
|
|
|
expect(events[0].data.name).toBe('new-feature');
|
2019-03-13 19:10:13 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should not import an existing feature', async () => {
|
2020-11-03 14:56:07 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
features: [
|
|
|
|
{
|
|
|
|
name: 'new-feature',
|
|
|
|
enabled: true,
|
|
|
|
strategies: [{ name: 'default' }],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureToggleStore.create('default', data.features[0]);
|
2020-11-03 14:56:07 +01:00
|
|
|
|
|
|
|
await stateService.import({ data, keepExisting: true });
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(0);
|
2020-11-03 14:56:07 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should not keep existing feature if drop-before-import', async () => {
|
2020-11-03 14:56:07 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
features: [
|
|
|
|
{
|
|
|
|
name: 'new-feature',
|
|
|
|
enabled: true,
|
|
|
|
strategies: [{ name: 'default' }],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureToggleStore.create('default', data.features[0]);
|
2020-11-03 14:56:07 +01:00
|
|
|
|
|
|
|
await stateService.import({
|
|
|
|
data,
|
|
|
|
keepExisting: true,
|
|
|
|
dropBeforeImport: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(2);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(events[0].type).toBe(DROP_FEATURES);
|
|
|
|
expect(events[1].type).toBe(FEATURE_IMPORT);
|
2020-11-03 14:56:07 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should drop feature before import if specified', async () => {
|
2019-03-13 19:10:13 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
features: [
|
|
|
|
{
|
|
|
|
name: 'new-feature',
|
|
|
|
enabled: true,
|
|
|
|
strategies: [{ name: 'default' }],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
await stateService.import({ data, dropBeforeImport: true });
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(2);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(events[0].type).toBe(DROP_FEATURES);
|
|
|
|
expect(events[1].type).toBe(FEATURE_IMPORT);
|
|
|
|
expect(events[1].data.name).toBe('new-feature');
|
2019-03-13 19:10:13 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should import a strategy', async () => {
|
2019-03-13 19:10:13 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
strategies: [
|
|
|
|
{
|
|
|
|
name: 'new-strategy',
|
|
|
|
parameters: [],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
await stateService.import({ data });
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(1);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(events[0].type).toBe(STRATEGY_IMPORT);
|
|
|
|
expect(events[0].data.name).toBe('new-strategy');
|
2019-03-13 19:10:13 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should not import an existing strategy', async () => {
|
2020-11-03 14:56:07 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
strategies: [
|
|
|
|
{
|
|
|
|
name: 'new-strategy',
|
|
|
|
parameters: [],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
2021-01-18 12:32:19 +01:00
|
|
|
await stores.strategyStore.createStrategy(data.strategies[0]);
|
2020-11-03 14:56:07 +01:00
|
|
|
|
|
|
|
await stateService.import({ data, keepExisting: true });
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(0);
|
2020-11-03 14:56:07 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should drop strategies before import if specified', async () => {
|
2019-03-13 19:10:13 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
strategies: [
|
|
|
|
{
|
|
|
|
name: 'new-strategy',
|
|
|
|
parameters: [],
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
await stateService.import({ data, dropBeforeImport: true });
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(2);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(events[0].type).toBe(DROP_STRATEGIES);
|
|
|
|
expect(events[1].type).toBe(STRATEGY_IMPORT);
|
|
|
|
expect(events[1].data.name).toBe('new-strategy');
|
2019-03-13 19:10:13 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should drop neither features nor strategies when neither is imported', async () => {
|
2019-03-13 19:10:13 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {};
|
|
|
|
|
|
|
|
await stateService.import({ data, dropBeforeImport: true });
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(0);
|
2019-03-13 19:10:13 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should not accept gibberish', async () => {
|
2019-03-13 19:10:13 +01:00
|
|
|
const { stateService } = getSetup();
|
|
|
|
|
|
|
|
const data1 = {
|
|
|
|
type: 'gibberish',
|
|
|
|
flags: { evil: true },
|
|
|
|
};
|
|
|
|
const data2 = '{somerandomtext/';
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
await expect(async () =>
|
|
|
|
stateService.import({ data: data1 }),
|
|
|
|
).rejects.toThrow();
|
2019-03-13 19:10:13 +01:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
await expect(async () =>
|
|
|
|
stateService.import({ data: data2 }),
|
|
|
|
).rejects.toThrow();
|
2019-03-13 19:10:13 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should export featureToggles', async () => {
|
2019-03-13 19:10:13 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureToggleStore.create('default', {
|
2021-08-12 15:04:37 +02:00
|
|
|
name: 'a-feature',
|
|
|
|
});
|
2019-03-13 19:10:13 +01:00
|
|
|
|
2019-03-14 17:56:02 +01:00
|
|
|
const data = await stateService.export({ includeFeatureToggles: true });
|
2019-03-13 19:10:13 +01:00
|
|
|
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(data.features).toHaveLength(1);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(data.features[0].name).toBe('a-feature');
|
2019-03-13 19:10:13 +01:00
|
|
|
});
|
|
|
|
|
2021-09-24 08:55:53 +02:00
|
|
|
test('archived feature toggles should not be included', async () => {
|
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
await stores.featureToggleStore.create('default', {
|
|
|
|
name: 'a-feature',
|
|
|
|
archived: true,
|
|
|
|
});
|
|
|
|
const data = await stateService.export({ includeFeatureToggles: true });
|
|
|
|
|
|
|
|
expect(data.features).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('featureStrategy connected to an archived feature toggle should not be included', async () => {
|
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
const featureName = 'fstrat-archived-feature';
|
|
|
|
await stores.featureToggleStore.create('default', {
|
|
|
|
name: featureName,
|
|
|
|
archived: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
await stores.featureStrategiesStore.createStrategyFeatureEnv({
|
|
|
|
featureName,
|
|
|
|
strategyName: 'fstrat-archived-strat',
|
|
|
|
environment: GLOBAL_ENV,
|
|
|
|
constraints: [],
|
|
|
|
parameters: {},
|
|
|
|
projectId: 'default',
|
|
|
|
});
|
|
|
|
const data = await stateService.export({ includeFeatureToggles: true });
|
|
|
|
expect(data.featureStrategies).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('featureStrategy connected to a feature should be included', async () => {
|
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
const featureName = 'fstrat-feature';
|
|
|
|
await stores.featureToggleStore.create('default', {
|
|
|
|
name: featureName,
|
|
|
|
});
|
|
|
|
|
|
|
|
await stores.featureStrategiesStore.createStrategyFeatureEnv({
|
|
|
|
featureName,
|
|
|
|
strategyName: 'fstrat-strat',
|
|
|
|
environment: GLOBAL_ENV,
|
|
|
|
constraints: [],
|
|
|
|
parameters: {},
|
|
|
|
projectId: 'default',
|
|
|
|
});
|
|
|
|
const data = await stateService.export({ includeFeatureToggles: true });
|
|
|
|
expect(data.featureStrategies).toHaveLength(1);
|
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should export strategies', async () => {
|
2019-03-13 19:10:13 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
await stores.strategyStore.createStrategy({
|
|
|
|
name: 'a-strategy',
|
|
|
|
editable: true,
|
|
|
|
});
|
2019-03-13 19:10:13 +01:00
|
|
|
|
2019-03-14 17:56:02 +01:00
|
|
|
const data = await stateService.export({ includeStrategies: true });
|
2019-03-13 19:10:13 +01:00
|
|
|
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(data.strategies).toHaveLength(1);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(data.strategies[0].name).toBe('a-strategy');
|
2019-03-13 19:10:13 +01:00
|
|
|
});
|
2021-03-12 11:08:10 +01:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should import a tag and tag type', async () => {
|
2021-03-12 11:08:10 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
const data = {
|
|
|
|
tagTypes: [
|
|
|
|
{ name: 'simple', description: 'some description', icon: '#' },
|
|
|
|
],
|
|
|
|
tags: [{ type: 'simple', value: 'test' }],
|
|
|
|
};
|
2021-08-10 13:50:59 +02:00
|
|
|
|
2021-03-12 11:08:10 +01:00
|
|
|
await stateService.import({ data });
|
2021-08-10 13:50:59 +02:00
|
|
|
|
2021-03-12 11:08:10 +01:00
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-08-10 13:50:59 +02:00
|
|
|
expect(events).toHaveLength(2);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(events[0].type).toBe(TAG_TYPE_IMPORT);
|
|
|
|
expect(events[0].data.name).toBe('simple');
|
|
|
|
expect(events[1].type).toBe(TAG_IMPORT);
|
|
|
|
expect(events[1].data.value).toBe('test');
|
2021-03-12 11:08:10 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('Should not import an existing tag', async () => {
|
2021-03-12 11:08:10 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
const data = {
|
|
|
|
tagTypes: [
|
|
|
|
{ name: 'simple', description: 'some description', icon: '#' },
|
|
|
|
],
|
|
|
|
tags: [{ type: 'simple', value: 'test' }],
|
|
|
|
featureTags: [
|
|
|
|
{
|
|
|
|
featureName: 'demo-feature',
|
|
|
|
tagType: 'simple',
|
|
|
|
tagValue: 'test',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await stores.tagTypeStore.createTagType(data.tagTypes[0]);
|
|
|
|
await stores.tagStore.createTag(data.tags[0]);
|
2021-07-07 10:46:50 +02:00
|
|
|
await stores.featureTagStore.tagFeature(data.featureTags[0].featureName, {
|
|
|
|
type: data.featureTags[0].tagType,
|
|
|
|
value: data.featureTags[0].tagValue,
|
|
|
|
});
|
2021-03-12 11:08:10 +01:00
|
|
|
await stateService.import({ data, keepExisting: true });
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(0);
|
2021-03-12 11:08:10 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('Should not keep existing tags if drop-before-import', async () => {
|
2021-03-12 11:08:10 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
const notSoSimple = {
|
|
|
|
name: 'notsosimple',
|
|
|
|
description: 'some other description',
|
|
|
|
icon: '#',
|
|
|
|
};
|
|
|
|
const slack = {
|
|
|
|
name: 'slack',
|
|
|
|
description: 'slack tags',
|
|
|
|
icon: '#',
|
|
|
|
};
|
|
|
|
|
|
|
|
await stores.tagTypeStore.createTagType(notSoSimple);
|
|
|
|
await stores.tagTypeStore.createTagType(slack);
|
|
|
|
const data = {
|
|
|
|
tagTypes: [
|
|
|
|
{ name: 'simple', description: 'some description', icon: '#' },
|
|
|
|
],
|
|
|
|
tags: [{ type: 'simple', value: 'test' }],
|
|
|
|
featureTags: [
|
|
|
|
{
|
|
|
|
featureName: 'demo-feature',
|
|
|
|
tagType: 'simple',
|
|
|
|
tagValue: 'test',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await stateService.import({ data, dropBeforeImport: true });
|
|
|
|
const tagTypes = await stores.tagTypeStore.getAll();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(tagTypes).toHaveLength(1);
|
2021-03-12 11:08:10 +01:00
|
|
|
});
|
|
|
|
|
2021-08-12 15:04:37 +02:00
|
|
|
test('should export tag, tagtypes but not feature tags if the feature is not exported', async () => {
|
2021-03-12 11:08:10 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
tagTypes: [
|
|
|
|
{ name: 'simple', description: 'some description', icon: '#' },
|
|
|
|
],
|
|
|
|
tags: [{ type: 'simple', value: 'test' }],
|
|
|
|
featureTags: [
|
|
|
|
{
|
|
|
|
featureName: 'demo-feature',
|
|
|
|
tagType: 'simple',
|
|
|
|
tagValue: 'test',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await stores.tagTypeStore.createTagType(data.tagTypes[0]);
|
|
|
|
await stores.tagStore.createTag(data.tags[0]);
|
2021-07-07 10:46:50 +02:00
|
|
|
await stores.featureTagStore.tagFeature(data.featureTags[0].featureName, {
|
|
|
|
type: data.featureTags[0].tagType,
|
|
|
|
value: data.featureTags[0].tagValue,
|
|
|
|
});
|
2021-03-12 11:08:10 +01:00
|
|
|
|
|
|
|
const exported = await stateService.export({
|
|
|
|
includeFeatureToggles: false,
|
|
|
|
includeStrategies: false,
|
|
|
|
includeTags: true,
|
|
|
|
includeProjects: false,
|
|
|
|
});
|
2021-08-10 13:50:59 +02:00
|
|
|
|
|
|
|
expect(exported.tags).toHaveLength(1);
|
|
|
|
expect(exported.tags[0].type).toBe(data.tags[0].type);
|
|
|
|
expect(exported.tags[0].value).toBe(data.tags[0].value);
|
|
|
|
expect(exported.tagTypes).toHaveLength(1);
|
|
|
|
expect(exported.tagTypes[0].name).toBe(data.tagTypes[0].name);
|
|
|
|
expect(exported.featureTags).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('should export tag, tagtypes, featureTags and features', async () => {
|
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
tagTypes: [
|
|
|
|
{ name: 'simple', description: 'some description', icon: '#' },
|
|
|
|
],
|
|
|
|
tags: [{ type: 'simple', value: 'test' }],
|
|
|
|
featureTags: [
|
|
|
|
{
|
|
|
|
featureName: 'demo-feature',
|
|
|
|
tagType: 'simple',
|
|
|
|
tagValue: 'test',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await stores.tagTypeStore.createTagType(data.tagTypes[0]);
|
|
|
|
await stores.tagStore.createTag(data.tags[0]);
|
|
|
|
await stores.featureTagStore.tagFeature(data.featureTags[0].featureName, {
|
|
|
|
type: data.featureTags[0].tagType,
|
|
|
|
value: data.featureTags[0].tagValue,
|
|
|
|
});
|
|
|
|
|
|
|
|
const exported = await stateService.export({
|
|
|
|
includeFeatureToggles: true,
|
|
|
|
includeStrategies: false,
|
|
|
|
includeTags: true,
|
|
|
|
includeProjects: false,
|
|
|
|
});
|
|
|
|
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(exported.tags).toHaveLength(1);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(exported.tags[0].type).toBe(data.tags[0].type);
|
|
|
|
expect(exported.tags[0].value).toBe(data.tags[0].value);
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(exported.tagTypes).toHaveLength(1);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(exported.tagTypes[0].name).toBe(data.tagTypes[0].name);
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(exported.featureTags).toHaveLength(1);
|
2021-08-10 13:50:59 +02:00
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(exported.featureTags[0].featureName).toBe(
|
|
|
|
data.featureTags[0].featureName,
|
|
|
|
);
|
|
|
|
expect(exported.featureTags[0].tagType).toBe(data.featureTags[0].tagType);
|
|
|
|
expect(exported.featureTags[0].tagValue).toBe(data.featureTags[0].tagValue);
|
2021-03-12 11:08:10 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('should import a project', async () => {
|
2021-03-12 11:08:10 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
projects: [
|
|
|
|
{
|
|
|
|
id: 'default',
|
|
|
|
name: 'default',
|
|
|
|
description: 'Some fancy description for project',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
|
|
|
|
await stateService.import({ data });
|
|
|
|
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(1);
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(events[0].type).toBe(PROJECT_IMPORT);
|
|
|
|
expect(events[0].data.name).toBe('default');
|
2021-03-12 11:08:10 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('Should not import an existing project', async () => {
|
2021-03-12 11:08:10 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
projects: [
|
|
|
|
{
|
|
|
|
id: 'default',
|
|
|
|
name: 'default',
|
|
|
|
description: 'Some fancy description for project',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await stores.projectStore.create(data.projects[0]);
|
|
|
|
|
|
|
|
await stateService.import({ data, keepExisting: true });
|
|
|
|
const events = await stores.eventStore.getEvents();
|
2021-07-07 10:46:50 +02:00
|
|
|
expect(events).toHaveLength(0);
|
2021-03-12 11:08:10 +01:00
|
|
|
|
|
|
|
await stateService.import({ data });
|
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('Should drop projects before import if specified', async () => {
|
2021-03-12 11:08:10 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
|
|
|
|
const data = {
|
|
|
|
projects: [
|
|
|
|
{
|
|
|
|
id: 'default',
|
|
|
|
name: 'default',
|
|
|
|
description: 'Some fancy description for project',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
};
|
|
|
|
await stores.projectStore.create({
|
|
|
|
id: 'fancy',
|
|
|
|
name: 'extra',
|
|
|
|
description: 'Not expected to be seen after import',
|
|
|
|
});
|
|
|
|
await stateService.import({ data, dropBeforeImport: true });
|
2021-08-12 15:04:37 +02:00
|
|
|
const hasProject = await stores.projectStore.hasProject('fancy');
|
|
|
|
expect(hasProject).toBe(false);
|
2021-03-12 11:08:10 +01:00
|
|
|
});
|
|
|
|
|
2021-05-28 11:10:24 +02:00
|
|
|
test('Should export projects', async () => {
|
2021-03-12 11:08:10 +01:00
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
await stores.projectStore.create({
|
|
|
|
id: 'fancy',
|
|
|
|
name: 'extra',
|
|
|
|
description: 'No surprises here',
|
|
|
|
});
|
|
|
|
const exported = await stateService.export({
|
|
|
|
includeFeatureToggles: false,
|
|
|
|
includeStrategies: false,
|
|
|
|
includeTags: false,
|
|
|
|
includeProjects: true,
|
|
|
|
});
|
2021-05-28 11:10:24 +02:00
|
|
|
expect(exported.projects[0].id).toBe('fancy');
|
|
|
|
expect(exported.projects[0].name).toBe('extra');
|
|
|
|
expect(exported.projects[0].description).toBe('No surprises here');
|
2021-03-12 11:08:10 +01:00
|
|
|
});
|
2021-07-07 10:46:50 +02:00
|
|
|
|
|
|
|
test('exporting to new format works', async () => {
|
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
await stores.projectStore.create({
|
|
|
|
id: 'fancy',
|
|
|
|
name: 'extra',
|
|
|
|
description: 'No surprises here',
|
|
|
|
});
|
2021-09-13 15:57:38 +02:00
|
|
|
await stores.environmentStore.create({
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'dev',
|
2021-09-13 15:57:38 +02:00
|
|
|
type: 'development',
|
2021-07-07 10:46:50 +02:00
|
|
|
});
|
2021-09-13 15:57:38 +02:00
|
|
|
await stores.environmentStore.create({
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'prod',
|
2021-09-13 15:57:38 +02:00
|
|
|
type: 'production',
|
2021-07-07 10:46:50 +02:00
|
|
|
});
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureToggleStore.create('fancy', {
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'Some-feature',
|
|
|
|
});
|
|
|
|
await stores.strategyStore.createStrategy({ name: 'format' });
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureEnvironmentStore.addEnvironmentToFeature(
|
2021-07-07 10:46:50 +02:00
|
|
|
'Some-feature',
|
|
|
|
'dev',
|
|
|
|
true,
|
|
|
|
);
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureStrategiesStore.createStrategyFeatureEnv({
|
2021-07-07 10:46:50 +02:00
|
|
|
featureName: 'Some-feature',
|
2021-09-13 10:23:57 +02:00
|
|
|
projectId: 'fancy',
|
2021-07-07 10:46:50 +02:00
|
|
|
strategyName: 'format',
|
|
|
|
environment: 'dev',
|
|
|
|
parameters: {},
|
|
|
|
constraints: [],
|
|
|
|
});
|
|
|
|
await stores.featureTagStore.tagFeature('Some-feature', {
|
|
|
|
type: 'simple',
|
|
|
|
value: 'Test',
|
|
|
|
});
|
|
|
|
const exported = await stateService.export({});
|
|
|
|
expect(exported.featureStrategies).toHaveLength(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('featureStrategies can keep existing', async () => {
|
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
await stores.projectStore.create({
|
|
|
|
id: 'fancy',
|
|
|
|
name: 'extra',
|
|
|
|
description: 'No surprises here',
|
|
|
|
});
|
2021-09-13 15:57:38 +02:00
|
|
|
await stores.environmentStore.create({
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'dev',
|
2021-09-13 15:57:38 +02:00
|
|
|
type: 'development',
|
2021-07-07 10:46:50 +02:00
|
|
|
});
|
2021-09-13 15:57:38 +02:00
|
|
|
await stores.environmentStore.create({
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'prod',
|
2021-09-13 15:57:38 +02:00
|
|
|
type: 'production',
|
2021-07-07 10:46:50 +02:00
|
|
|
});
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureToggleStore.create('fancy', {
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'Some-feature',
|
|
|
|
});
|
|
|
|
await stores.strategyStore.createStrategy({ name: 'format' });
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureEnvironmentStore.addEnvironmentToFeature(
|
2021-07-07 10:46:50 +02:00
|
|
|
'Some-feature',
|
|
|
|
'dev',
|
|
|
|
true,
|
|
|
|
);
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureStrategiesStore.createStrategyFeatureEnv({
|
2021-07-07 10:46:50 +02:00
|
|
|
featureName: 'Some-feature',
|
2021-09-13 10:23:57 +02:00
|
|
|
projectId: 'fancy',
|
2021-07-07 10:46:50 +02:00
|
|
|
strategyName: 'format',
|
|
|
|
environment: 'dev',
|
|
|
|
parameters: {},
|
|
|
|
constraints: [],
|
|
|
|
});
|
|
|
|
await stores.featureTagStore.tagFeature('Some-feature', {
|
|
|
|
type: 'simple',
|
|
|
|
value: 'Test',
|
|
|
|
});
|
|
|
|
|
|
|
|
const exported = await stateService.export({});
|
|
|
|
await stateService.import({
|
|
|
|
data: exported,
|
|
|
|
userName: 'testing',
|
|
|
|
keepExisting: true,
|
|
|
|
});
|
|
|
|
expect(await stores.featureStrategiesStore.getAll()).toHaveLength(1);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('featureStrategies should not keep existing if dropBeforeImport', async () => {
|
|
|
|
const { stateService, stores } = getSetup();
|
|
|
|
await stores.projectStore.create({
|
|
|
|
id: 'fancy',
|
|
|
|
name: 'extra',
|
|
|
|
description: 'No surprises here',
|
|
|
|
});
|
2021-09-13 15:57:38 +02:00
|
|
|
await stores.environmentStore.create({
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'dev',
|
2021-09-13 15:57:38 +02:00
|
|
|
type: 'development',
|
2021-07-07 10:46:50 +02:00
|
|
|
});
|
2021-09-13 15:57:38 +02:00
|
|
|
await stores.environmentStore.create({
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'prod',
|
2021-09-13 15:57:38 +02:00
|
|
|
type: 'production',
|
2021-07-07 10:46:50 +02:00
|
|
|
});
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureToggleStore.create('fancy', {
|
2021-07-07 10:46:50 +02:00
|
|
|
name: 'Some-feature',
|
|
|
|
});
|
|
|
|
await stores.strategyStore.createStrategy({ name: 'format' });
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureEnvironmentStore.addEnvironmentToFeature(
|
2021-07-07 10:46:50 +02:00
|
|
|
'Some-feature',
|
|
|
|
'dev',
|
|
|
|
true,
|
|
|
|
);
|
2021-09-13 10:23:57 +02:00
|
|
|
await stores.featureStrategiesStore.createStrategyFeatureEnv({
|
2021-07-07 10:46:50 +02:00
|
|
|
featureName: 'Some-feature',
|
2021-09-13 10:23:57 +02:00
|
|
|
projectId: 'fancy',
|
2021-07-07 10:46:50 +02:00
|
|
|
strategyName: 'format',
|
|
|
|
environment: 'dev',
|
|
|
|
parameters: {},
|
|
|
|
constraints: [],
|
|
|
|
});
|
|
|
|
await stores.featureTagStore.tagFeature('Some-feature', {
|
|
|
|
type: 'simple',
|
|
|
|
value: 'Test',
|
|
|
|
});
|
|
|
|
|
|
|
|
const exported = await stateService.export({});
|
|
|
|
exported.featureStrategies = [];
|
|
|
|
await stateService.import({
|
|
|
|
data: exported,
|
|
|
|
userName: 'testing',
|
|
|
|
keepExisting: true,
|
|
|
|
dropBeforeImport: true,
|
|
|
|
});
|
|
|
|
expect(await stores.featureStrategiesStore.getAll()).toHaveLength(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('Import v1 and exporting v2 should work', async () => {
|
|
|
|
const { stateService } = getSetup();
|
|
|
|
await stateService.import({
|
|
|
|
data: oldExportExample,
|
|
|
|
dropBeforeImport: true,
|
|
|
|
userName: 'testing',
|
|
|
|
});
|
|
|
|
const exported = await stateService.export({});
|
|
|
|
const strategiesCount = oldExportExample.features.reduce(
|
|
|
|
(acc, f) => acc + f.strategies.length,
|
|
|
|
0,
|
|
|
|
);
|
|
|
|
expect(
|
2021-08-12 15:04:37 +02:00
|
|
|
exported.features.every((f) =>
|
|
|
|
oldExportExample.features.some((old) => old.name === f.name),
|
2021-07-07 10:46:50 +02:00
|
|
|
),
|
|
|
|
).toBeTruthy();
|
|
|
|
expect(exported.featureStrategies).toHaveLength(strategiesCount);
|
|
|
|
});
|