mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: extract custom context fields from all possible locations (#3118)
This commit is contained in:
		
							parent
							
								
									90bbbc327b
								
							
						
					
					
						commit
						e06ecab642
					
				@ -106,14 +106,26 @@ export default class ExportImportService {
 | 
				
			|||||||
            this.tagTypeStore.getAll(),
 | 
					            this.tagTypeStore.getAll(),
 | 
				
			||||||
        ]);
 | 
					        ]);
 | 
				
			||||||
        this.addSegmentsToStrategies(featureStrategies, strategySegments);
 | 
					        this.addSegmentsToStrategies(featureStrategies, strategySegments);
 | 
				
			||||||
        const filteredContextFields = contextFields.filter((field) =>
 | 
					        const filteredContextFields = contextFields.filter(
 | 
				
			||||||
            featureStrategies.some(
 | 
					            (field) =>
 | 
				
			||||||
                (strategy) =>
 | 
					                featureEnvironments.some((featureEnv) =>
 | 
				
			||||||
                    strategy.parameters.stickiness === field.name ||
 | 
					                    featureEnv.variants.some(
 | 
				
			||||||
                    strategy.constraints.some(
 | 
					                        (variant) =>
 | 
				
			||||||
                        (constraint) => constraint.contextName === field.name,
 | 
					                            variant.stickiness === field.name ||
 | 
				
			||||||
 | 
					                            variant.overrides.some(
 | 
				
			||||||
 | 
					                                (override) =>
 | 
				
			||||||
 | 
					                                    override.contextName === field.name,
 | 
				
			||||||
 | 
					                            ),
 | 
				
			||||||
                    ),
 | 
					                    ),
 | 
				
			||||||
            ),
 | 
					                ) ||
 | 
				
			||||||
 | 
					                featureStrategies.some(
 | 
				
			||||||
 | 
					                    (strategy) =>
 | 
				
			||||||
 | 
					                        strategy.parameters.stickiness === field.name ||
 | 
				
			||||||
 | 
					                        strategy.constraints.some(
 | 
				
			||||||
 | 
					                            (constraint) =>
 | 
				
			||||||
 | 
					                                constraint.contextName === field.name,
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        const filteredSegments = segments.filter((segment) =>
 | 
					        const filteredSegments = segments.filter((segment) =>
 | 
				
			||||||
            featureStrategies.some((strategy) =>
 | 
					            featureStrategies.some((strategy) =>
 | 
				
			||||||
 | 
				
			|||||||
@ -63,9 +63,9 @@ test('Can schedule multiple jobs at the different intervals', async () => {
 | 
				
			|||||||
    const job = jest.fn();
 | 
					    const job = jest.fn();
 | 
				
			||||||
    const anotherJob = jest.fn();
 | 
					    const anotherJob = jest.fn();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    schedulerService.schedule(job, 10);
 | 
					    schedulerService.schedule(job, 100);
 | 
				
			||||||
    schedulerService.schedule(anotherJob, 20);
 | 
					    schedulerService.schedule(anotherJob, 200);
 | 
				
			||||||
    await ms(25);
 | 
					    await ms(250);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    expect(job).toBeCalledTimes(3);
 | 
					    expect(job).toBeCalledTimes(3);
 | 
				
			||||||
    expect(anotherJob).toBeCalledTimes(2);
 | 
					    expect(anotherJob).toBeCalledTimes(2);
 | 
				
			||||||
 | 
				
			|||||||
@ -4,17 +4,19 @@ import {
 | 
				
			|||||||
} from '../../helpers/test-helper';
 | 
					} from '../../helpers/test-helper';
 | 
				
			||||||
import dbInit, { ITestDb } from '../../helpers/database-init';
 | 
					import dbInit, { ITestDb } from '../../helpers/database-init';
 | 
				
			||||||
import getLogger from '../../../fixtures/no-logger';
 | 
					import getLogger from '../../../fixtures/no-logger';
 | 
				
			||||||
import { IEventStore } from 'lib/types/stores/event-store';
 | 
					 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
    FeatureToggleDTO,
 | 
					    FeatureToggleDTO,
 | 
				
			||||||
    IEnvironmentStore,
 | 
					    IEnvironmentStore,
 | 
				
			||||||
 | 
					    IEventStore,
 | 
				
			||||||
    IFeatureToggleStore,
 | 
					    IFeatureToggleStore,
 | 
				
			||||||
    IProjectStore,
 | 
					    IProjectStore,
 | 
				
			||||||
    ISegment,
 | 
					    ISegment,
 | 
				
			||||||
    IStrategyConfig,
 | 
					    IStrategyConfig,
 | 
				
			||||||
 | 
					    IVariant,
 | 
				
			||||||
} from 'lib/types';
 | 
					} from 'lib/types';
 | 
				
			||||||
import { DEFAULT_ENV } from '../../../../lib/util';
 | 
					import { DEFAULT_ENV } from '../../../../lib/util';
 | 
				
			||||||
import { ContextFieldSchema } from '../../../../lib/openapi';
 | 
					import { ContextFieldSchema } from '../../../../lib/openapi';
 | 
				
			||||||
 | 
					import User from '../../../../lib/types/user';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let app: IUnleashTest;
 | 
					let app: IUnleashTest;
 | 
				
			||||||
let db: ITestDb;
 | 
					let db: ITestDb;
 | 
				
			||||||
@ -79,6 +81,21 @@ const createContext = async (context: ContextFieldSchema = defaultContext) => {
 | 
				
			|||||||
        .expect(201);
 | 
					        .expect(201);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const createVariants = async (
 | 
				
			||||||
 | 
					    project: string,
 | 
				
			||||||
 | 
					    feature: string,
 | 
				
			||||||
 | 
					    environment: string,
 | 
				
			||||||
 | 
					    variants: IVariant[],
 | 
				
			||||||
 | 
					) => {
 | 
				
			||||||
 | 
					    await app.services.featureToggleService.saveVariantsOnEnv(
 | 
				
			||||||
 | 
					        project,
 | 
				
			||||||
 | 
					        feature,
 | 
				
			||||||
 | 
					        environment,
 | 
				
			||||||
 | 
					        variants,
 | 
				
			||||||
 | 
					        new User({ id: 1 }),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const createProject = async (project: string, environment: string) => {
 | 
					const createProject = async (project: string, environment: string) => {
 | 
				
			||||||
    await db.stores.environmentStore.create({
 | 
					    await db.stores.environmentStore.create({
 | 
				
			||||||
        name: environment,
 | 
					        name: environment,
 | 
				
			||||||
@ -192,24 +209,32 @@ test('exports features', async () => {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test('should export custom context fields', async () => {
 | 
					test('should export custom context fields from strategies and variants', async () => {
 | 
				
			||||||
    await createProject('default', 'default');
 | 
					    await createProject('default', 'default');
 | 
				
			||||||
    const context = {
 | 
					    const strategyContext = {
 | 
				
			||||||
        name: 'test-export',
 | 
					        name: 'strategy-context',
 | 
				
			||||||
        legalValues: [
 | 
					        legalValues: [
 | 
				
			||||||
            { value: 'estonia' },
 | 
					            { value: 'strategy-context-1' },
 | 
				
			||||||
            { value: 'norway' },
 | 
					            { value: 'strategy-context-2' },
 | 
				
			||||||
            { value: 'poland' },
 | 
					            { value: 'strategy-context-3' },
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    await createContext(context);
 | 
					    const strategyStickinessContext = {
 | 
				
			||||||
 | 
					        name: 'strategy-stickiness',
 | 
				
			||||||
 | 
					        legalValues: [
 | 
				
			||||||
 | 
					            { value: 'strategy-stickiness-1' },
 | 
				
			||||||
 | 
					            { value: 'strategy-stickiness-2' },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    await createContext(strategyContext);
 | 
				
			||||||
 | 
					    await createContext(strategyStickinessContext);
 | 
				
			||||||
    const strategy = {
 | 
					    const strategy = {
 | 
				
			||||||
        name: 'default',
 | 
					        name: 'default',
 | 
				
			||||||
        parameters: { rollout: '100', stickiness: 'default' },
 | 
					        parameters: { rollout: '100', stickiness: 'strategy-stickiness' },
 | 
				
			||||||
        constraints: [
 | 
					        constraints: [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                contextName: context.name,
 | 
					                contextName: strategyContext.name,
 | 
				
			||||||
                values: ['estonia', 'norway'],
 | 
					                values: ['strategy-context-1', 'strategy-context-2'],
 | 
				
			||||||
                operator: 'IN' as const,
 | 
					                operator: 'IN' as const,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
@ -221,6 +246,36 @@ test('should export custom context fields', async () => {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        strategy,
 | 
					        strategy,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					    const variantStickinessContext = {
 | 
				
			||||||
 | 
					        name: 'variant-stickiness-context',
 | 
				
			||||||
 | 
					        legalValues: [
 | 
				
			||||||
 | 
					            { value: 'variant-stickiness-context-1' },
 | 
				
			||||||
 | 
					            { value: 'variant-stickiness-context-2' },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    const variantOverridesContext = {
 | 
				
			||||||
 | 
					        name: 'variant-overrides-context',
 | 
				
			||||||
 | 
					        legalValues: [
 | 
				
			||||||
 | 
					            { value: 'variant-overrides-context-1' },
 | 
				
			||||||
 | 
					            { value: 'variant-overrides-context-2' },
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    await createContext(variantStickinessContext);
 | 
				
			||||||
 | 
					    await createContext(variantOverridesContext);
 | 
				
			||||||
 | 
					    await createVariants('default', 'first_feature', 'default', [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            name: 'irrelevant',
 | 
				
			||||||
 | 
					            weight: 1000,
 | 
				
			||||||
 | 
					            stickiness: 'variant-stickiness-context',
 | 
				
			||||||
 | 
					            weightType: 'variable',
 | 
				
			||||||
 | 
					            overrides: [
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    contextName: 'variant-overrides-context',
 | 
				
			||||||
 | 
					                    values: ['variant-overrides-context-1'],
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { body } = await app.request
 | 
					    const { body } = await app.request
 | 
				
			||||||
        .post('/api/admin/features-batch/export')
 | 
					        .post('/api/admin/features-batch/export')
 | 
				
			||||||
@ -246,7 +301,12 @@ test('should export custom context fields', async () => {
 | 
				
			|||||||
                featureName: 'first_feature',
 | 
					                featureName: 'first_feature',
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        contextFields: [context],
 | 
					        contextFields: [
 | 
				
			||||||
 | 
					            strategyContext,
 | 
				
			||||||
 | 
					            strategyStickinessContext,
 | 
				
			||||||
 | 
					            variantOverridesContext,
 | 
				
			||||||
 | 
					            variantStickinessContext,
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user