mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: copy feature with parent (#4918)
This commit is contained in:
		
							parent
							
								
									5141d9db67
								
							
						
					
					
						commit
						257414424d
					
				@ -84,7 +84,7 @@ export const AddDependencyDialogue = ({
 | 
			
		||||
            secondaryButtonText='Cancel'
 | 
			
		||||
        >
 | 
			
		||||
            <Box>
 | 
			
		||||
                You feature will be evaluated only when the selected parent
 | 
			
		||||
                Your feature will be evaluated only when the selected parent
 | 
			
		||||
                feature is enabled in the same environment.
 | 
			
		||||
                <br />
 | 
			
		||||
                <br />
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,32 @@ export class DependentFeaturesService {
 | 
			
		||||
        this.eventService = eventService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async cloneDependencies(
 | 
			
		||||
        {
 | 
			
		||||
            featureName,
 | 
			
		||||
            newFeatureName,
 | 
			
		||||
            projectId,
 | 
			
		||||
        }: { featureName: string; newFeatureName: string; projectId: string },
 | 
			
		||||
        user: string,
 | 
			
		||||
    ) {
 | 
			
		||||
        const parents = await this.dependentFeaturesReadModel.getParents(
 | 
			
		||||
            featureName,
 | 
			
		||||
        );
 | 
			
		||||
        await Promise.all(
 | 
			
		||||
            parents.map((parent) =>
 | 
			
		||||
                this.upsertFeatureDependency(
 | 
			
		||||
                    { child: newFeatureName, projectId },
 | 
			
		||||
                    {
 | 
			
		||||
                        feature: parent.feature,
 | 
			
		||||
                        enabled: parent.enabled,
 | 
			
		||||
                        variants: parent.variants,
 | 
			
		||||
                    },
 | 
			
		||||
                    user,
 | 
			
		||||
                ),
 | 
			
		||||
            ),
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async upsertFeatureDependency(
 | 
			
		||||
        { child, projectId }: { child: string; projectId: string },
 | 
			
		||||
        dependentFeature: CreateDependentFeatureSchema,
 | 
			
		||||
 | 
			
		||||
@ -48,6 +48,10 @@ import { DependentFeaturesReadModel } from '../dependent-features/dependent-feat
 | 
			
		||||
import { FakeDependentFeaturesReadModel } from '../dependent-features/fake-dependent-features-read-model';
 | 
			
		||||
import FeatureTagStore from '../../db/feature-tag-store';
 | 
			
		||||
import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store';
 | 
			
		||||
import {
 | 
			
		||||
    createDependentFeaturesService,
 | 
			
		||||
    createFakeDependentFeaturesService,
 | 
			
		||||
} from '../dependent-features/createDependentFeaturesService';
 | 
			
		||||
 | 
			
		||||
export const createFeatureToggleService = (
 | 
			
		||||
    db: Db,
 | 
			
		||||
@ -115,6 +119,8 @@ export const createFeatureToggleService = (
 | 
			
		||||
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(db);
 | 
			
		||||
 | 
			
		||||
    const dependentFeaturesService = createDependentFeaturesService(db, config);
 | 
			
		||||
 | 
			
		||||
    const featureToggleService = new FeatureToggleService(
 | 
			
		||||
        {
 | 
			
		||||
            featureStrategiesStore,
 | 
			
		||||
@ -133,6 +139,7 @@ export const createFeatureToggleService = (
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
        dependentFeaturesService,
 | 
			
		||||
    );
 | 
			
		||||
    return featureToggleService;
 | 
			
		||||
};
 | 
			
		||||
@ -173,6 +180,7 @@ export const createFakeFeatureToggleService = (
 | 
			
		||||
    const changeRequestAccessReadModel = createFakeChangeRequestAccessService();
 | 
			
		||||
    const fakePrivateProjectChecker = createFakePrivateProjectChecker();
 | 
			
		||||
    const dependentFeaturesReadModel = new FakeDependentFeaturesReadModel();
 | 
			
		||||
    const dependentFeaturesService = createFakeDependentFeaturesService(config);
 | 
			
		||||
    const featureToggleService = new FeatureToggleService(
 | 
			
		||||
        {
 | 
			
		||||
            featureStrategiesStore,
 | 
			
		||||
@ -191,6 +199,7 @@ export const createFakeFeatureToggleService = (
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        fakePrivateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
        dependentFeaturesService,
 | 
			
		||||
    );
 | 
			
		||||
    return featureToggleService;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,7 @@ import { IPrivateProjectChecker } from '../features/private-project/privateProje
 | 
			
		||||
import { IDependentFeaturesReadModel } from '../features/dependent-features/dependent-features-read-model-type';
 | 
			
		||||
import EventService from './event-service';
 | 
			
		||||
import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store';
 | 
			
		||||
import { DependentFeaturesService } from '../features/dependent-features/dependent-features-service';
 | 
			
		||||
 | 
			
		||||
test('Should only store events for potentially stale on', async () => {
 | 
			
		||||
    expect.assertions(2);
 | 
			
		||||
@ -64,6 +65,7 @@ test('Should only store events for potentially stale on', async () => {
 | 
			
		||||
        {} as IChangeRequestAccessReadModel,
 | 
			
		||||
        {} as IPrivateProjectChecker,
 | 
			
		||||
        {} as IDependentFeaturesReadModel,
 | 
			
		||||
        {} as DependentFeaturesService,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    await featureToggleService.updatePotentiallyStaleFeatures();
 | 
			
		||||
 | 
			
		||||
@ -99,6 +99,7 @@ import { checkFeatureFlagNamesAgainstPattern } from '../features/feature-naming-
 | 
			
		||||
import { IPrivateProjectChecker } from '../features/private-project/privateProjectCheckerType';
 | 
			
		||||
import { IDependentFeaturesReadModel } from '../features/dependent-features/dependent-features-read-model-type';
 | 
			
		||||
import EventService from './event-service';
 | 
			
		||||
import { DependentFeaturesService } from '../features/dependent-features/dependent-features-service';
 | 
			
		||||
 | 
			
		||||
interface IFeatureContext {
 | 
			
		||||
    featureName: string;
 | 
			
		||||
@ -162,6 +163,8 @@ class FeatureToggleService {
 | 
			
		||||
 | 
			
		||||
    private dependentFeaturesReadModel: IDependentFeaturesReadModel;
 | 
			
		||||
 | 
			
		||||
    private dependentFeaturesService: DependentFeaturesService;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        {
 | 
			
		||||
            featureStrategiesStore,
 | 
			
		||||
@ -193,6 +196,7 @@ class FeatureToggleService {
 | 
			
		||||
        changeRequestAccessReadModel: IChangeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker: IPrivateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel: IDependentFeaturesReadModel,
 | 
			
		||||
        dependentFeaturesService: DependentFeaturesService,
 | 
			
		||||
    ) {
 | 
			
		||||
        this.logger = getLogger('services/feature-toggle-service.ts');
 | 
			
		||||
        this.featureStrategiesStore = featureStrategiesStore;
 | 
			
		||||
@ -210,6 +214,7 @@ class FeatureToggleService {
 | 
			
		||||
        this.changeRequestAccessReadModel = changeRequestAccessReadModel;
 | 
			
		||||
        this.privateProjectChecker = privateProjectChecker;
 | 
			
		||||
        this.dependentFeaturesReadModel = dependentFeaturesReadModel;
 | 
			
		||||
        this.dependentFeaturesService = dependentFeaturesService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async validateFeaturesContext(
 | 
			
		||||
@ -1255,7 +1260,17 @@ class FeatureToggleService {
 | 
			
		||||
            }),
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        await Promise.all([...strategyTasks, ...variantTasks]);
 | 
			
		||||
        const cloneDependencies =
 | 
			
		||||
            this.dependentFeaturesService.cloneDependencies(
 | 
			
		||||
                { featureName, newFeatureName, projectId },
 | 
			
		||||
                userName,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
        await Promise.all([
 | 
			
		||||
            ...strategyTasks,
 | 
			
		||||
            ...variantTasks,
 | 
			
		||||
            cloneDependencies,
 | 
			
		||||
        ]);
 | 
			
		||||
        return created;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -233,6 +233,13 @@ export const createServices = (
 | 
			
		||||
        config,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    const dependentFeaturesService = db
 | 
			
		||||
        ? createDependentFeaturesService(db, config)
 | 
			
		||||
        : createFakeDependentFeaturesService(config);
 | 
			
		||||
    const transactionalDependentFeaturesService = (txDb: Knex.Transaction) =>
 | 
			
		||||
        createDependentFeaturesService(txDb, config);
 | 
			
		||||
 | 
			
		||||
    const featureToggleServiceV2 = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
@ -242,6 +249,7 @@ export const createServices = (
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
        dependentFeaturesService,
 | 
			
		||||
    );
 | 
			
		||||
    const environmentService = new EnvironmentService(stores, config);
 | 
			
		||||
    const featureTagService = new FeatureTagService(
 | 
			
		||||
@ -327,12 +335,6 @@ export const createServices = (
 | 
			
		||||
 | 
			
		||||
    const eventAnnouncerService = new EventAnnouncerService(stores, config);
 | 
			
		||||
 | 
			
		||||
    const dependentFeaturesService = db
 | 
			
		||||
        ? createDependentFeaturesService(db, config)
 | 
			
		||||
        : createFakeDependentFeaturesService(config);
 | 
			
		||||
    const transactionalDependentFeaturesService = (txDb: Knex.Transaction) =>
 | 
			
		||||
        createDependentFeaturesService(txDb, config);
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
        accessService,
 | 
			
		||||
        accountService,
 | 
			
		||||
 | 
			
		||||
@ -295,6 +295,29 @@ test('Should not allow to archive/delete feature with children', async () => {
 | 
			
		||||
    );
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('should clone feature with parent dependencies', async () => {
 | 
			
		||||
    const parent = uuidv4();
 | 
			
		||||
    const child = uuidv4();
 | 
			
		||||
    const childClone = uuidv4();
 | 
			
		||||
    await app.createFeature(parent, 'default');
 | 
			
		||||
    await app.createFeature(child, 'default');
 | 
			
		||||
    await app.addDependency(child, parent);
 | 
			
		||||
 | 
			
		||||
    await app.request
 | 
			
		||||
        .post(`/api/admin/projects/default/features/${child}/clone`)
 | 
			
		||||
        .send({ name: childClone, replaceGroupId: false })
 | 
			
		||||
        .expect(201);
 | 
			
		||||
 | 
			
		||||
    const { body: clonedFeature } = await app.getProjectFeatures(
 | 
			
		||||
        'default',
 | 
			
		||||
        child,
 | 
			
		||||
    );
 | 
			
		||||
    expect(clonedFeature).toMatchObject({
 | 
			
		||||
        children: [],
 | 
			
		||||
        dependencies: [{ feature: parent, enabled: true, variants: [] }],
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
test('Can get features for project', async () => {
 | 
			
		||||
    await app.request
 | 
			
		||||
        .post('/api/admin/projects/default/features')
 | 
			
		||||
 | 
			
		||||
@ -13,25 +13,19 @@ import {
 | 
			
		||||
    IUnleashStores,
 | 
			
		||||
    IUserAccessOverview,
 | 
			
		||||
} from '../../../lib/types';
 | 
			
		||||
import FeatureToggleService from '../../../lib/services/feature-toggle-service';
 | 
			
		||||
import ProjectService from '../../../lib/services/project-service';
 | 
			
		||||
import { createTestConfig } from '../../config/test-config';
 | 
			
		||||
import { DEFAULT_PROJECT } from '../../../lib/types/project';
 | 
			
		||||
import { ALL_PROJECTS } from '../../../lib/util/constants';
 | 
			
		||||
import { SegmentService } from '../../../lib/services/segment-service';
 | 
			
		||||
import { GroupService } from '../../../lib/services/group-service';
 | 
			
		||||
import { EventService, FavoritesService } from '../../../lib/services';
 | 
			
		||||
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model';
 | 
			
		||||
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker';
 | 
			
		||||
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model';
 | 
			
		||||
import {
 | 
			
		||||
    createAccessService,
 | 
			
		||||
    createFeatureToggleService,
 | 
			
		||||
    createProjectService,
 | 
			
		||||
} from '../../../lib/features';
 | 
			
		||||
 | 
			
		||||
let db: ITestDb;
 | 
			
		||||
let stores: IUnleashStores;
 | 
			
		||||
let accessService: AccessService;
 | 
			
		||||
let eventService: EventService;
 | 
			
		||||
let groupService: GroupService;
 | 
			
		||||
let featureToggleService;
 | 
			
		||||
let favoritesService;
 | 
			
		||||
let projectService;
 | 
			
		||||
let editorUser;
 | 
			
		||||
let editorRole;
 | 
			
		||||
@ -238,51 +232,14 @@ beforeAll(async () => {
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        experimental: { environments: { enabled: true } },
 | 
			
		||||
    });
 | 
			
		||||
    eventService = new EventService(stores, config);
 | 
			
		||||
    groupService = new GroupService(stores, { getLogger }, eventService);
 | 
			
		||||
    accessService = new AccessService(stores, config, groupService);
 | 
			
		||||
    accessService = createAccessService(db.rawDatabase, config);
 | 
			
		||||
    const roles = await accessService.getRootRoles();
 | 
			
		||||
    editorRole = roles.find((r) => r.name === RoleName.EDITOR);
 | 
			
		||||
    adminRole = roles.find((r) => r.name === RoleName.ADMIN);
 | 
			
		||||
    readRole = roles.find((r) => r.name === RoleName.VIEWER);
 | 
			
		||||
    const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        accessService,
 | 
			
		||||
    );
 | 
			
		||||
    const privateProjectChecker = createPrivateProjectChecker(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        config,
 | 
			
		||||
    );
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
    featureToggleService = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        new SegmentService(
 | 
			
		||||
            stores,
 | 
			
		||||
            changeRequestAccessReadModel,
 | 
			
		||||
            config,
 | 
			
		||||
            eventService,
 | 
			
		||||
            privateProjectChecker,
 | 
			
		||||
        ),
 | 
			
		||||
        accessService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
    );
 | 
			
		||||
    favoritesService = new FavoritesService(stores, config, eventService);
 | 
			
		||||
    projectService = new ProjectService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        accessService,
 | 
			
		||||
        featureToggleService,
 | 
			
		||||
        groupService,
 | 
			
		||||
        favoritesService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    featureToggleService = createFeatureToggleService(db.rawDatabase, config);
 | 
			
		||||
    projectService = createProjectService(db.rawDatabase, config);
 | 
			
		||||
 | 
			
		||||
    editorUser = await createUser(editorRole.id);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -6,20 +6,13 @@ import { ApiTokenType, IApiToken } from '../../../lib/types/models/api-token';
 | 
			
		||||
import { DEFAULT_ENV } from '../../../lib/util/constants';
 | 
			
		||||
import { addDays, subDays } from 'date-fns';
 | 
			
		||||
import ProjectService from '../../../lib/services/project-service';
 | 
			
		||||
import FeatureToggleService from '../../../lib/services/feature-toggle-service';
 | 
			
		||||
import { AccessService } from '../../../lib/services/access-service';
 | 
			
		||||
import { SegmentService } from '../../../lib/services/segment-service';
 | 
			
		||||
import { GroupService } from '../../../lib/services/group-service';
 | 
			
		||||
import { EventService, FavoritesService } from '../../../lib/services';
 | 
			
		||||
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model';
 | 
			
		||||
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker';
 | 
			
		||||
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model';
 | 
			
		||||
import { EventService } from '../../../lib/services';
 | 
			
		||||
import { createProjectService } from '../../../lib/features';
 | 
			
		||||
 | 
			
		||||
let db;
 | 
			
		||||
let stores;
 | 
			
		||||
let apiTokenService: ApiTokenService;
 | 
			
		||||
let projectService: ProjectService;
 | 
			
		||||
let favoritesService: FavoritesService;
 | 
			
		||||
 | 
			
		||||
beforeAll(async () => {
 | 
			
		||||
    const config = createTestConfig({
 | 
			
		||||
@ -28,35 +21,6 @@ beforeAll(async () => {
 | 
			
		||||
    db = await dbInit('api_token_service_serial', getLogger);
 | 
			
		||||
    stores = db.stores;
 | 
			
		||||
    const eventService = new EventService(stores, config);
 | 
			
		||||
    const groupService = new GroupService(stores, config, eventService);
 | 
			
		||||
    const accessService = new AccessService(stores, config, groupService);
 | 
			
		||||
    const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        accessService,
 | 
			
		||||
    );
 | 
			
		||||
    const privateProjectChecker = createPrivateProjectChecker(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        config,
 | 
			
		||||
    );
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
    const featureToggleService = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        new SegmentService(
 | 
			
		||||
            stores,
 | 
			
		||||
            changeRequestAccessReadModel,
 | 
			
		||||
            config,
 | 
			
		||||
            eventService,
 | 
			
		||||
            privateProjectChecker,
 | 
			
		||||
        ),
 | 
			
		||||
        accessService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
    );
 | 
			
		||||
    const project = {
 | 
			
		||||
        id: 'test-project',
 | 
			
		||||
        name: 'Test Project',
 | 
			
		||||
@ -68,17 +32,7 @@ beforeAll(async () => {
 | 
			
		||||
        name: 'Some Name',
 | 
			
		||||
        email: 'test@getunleash.io',
 | 
			
		||||
    });
 | 
			
		||||
    favoritesService = new FavoritesService(stores, config, eventService);
 | 
			
		||||
    projectService = new ProjectService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        accessService,
 | 
			
		||||
        featureToggleService,
 | 
			
		||||
        groupService,
 | 
			
		||||
        favoritesService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
    );
 | 
			
		||||
    projectService = createProjectService(db.rawDatabase, config);
 | 
			
		||||
 | 
			
		||||
    await projectService.createProject(project, user);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,12 +2,6 @@ import FeatureToggleService from '../../../lib/services/feature-toggle-service';
 | 
			
		||||
import { createTestConfig } from '../../config/test-config';
 | 
			
		||||
import dbInit from '../helpers/database-init';
 | 
			
		||||
import { DEFAULT_ENV } from '../../../lib/util';
 | 
			
		||||
import {
 | 
			
		||||
    AccessService,
 | 
			
		||||
    EventService,
 | 
			
		||||
    GroupService,
 | 
			
		||||
    SegmentService,
 | 
			
		||||
} from '../../../lib/services';
 | 
			
		||||
import { FeatureStrategySchema } from '../../../lib/openapi';
 | 
			
		||||
import User from '../../../lib/types/user';
 | 
			
		||||
import {
 | 
			
		||||
@ -23,9 +17,10 @@ import {
 | 
			
		||||
    PermissionError,
 | 
			
		||||
} from '../../../lib/error';
 | 
			
		||||
import { ISegmentService } from '../../../lib/segments/segment-service-interface';
 | 
			
		||||
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model';
 | 
			
		||||
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker';
 | 
			
		||||
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model';
 | 
			
		||||
import {
 | 
			
		||||
    createFeatureToggleService,
 | 
			
		||||
    createSegmentService,
 | 
			
		||||
} from '../../../lib/features';
 | 
			
		||||
 | 
			
		||||
let stores: IUnleashStores;
 | 
			
		||||
let db;
 | 
			
		||||
@ -54,38 +49,10 @@ beforeAll(async () => {
 | 
			
		||||
    );
 | 
			
		||||
    unleashConfig = config;
 | 
			
		||||
    stores = db.stores;
 | 
			
		||||
    const eventService = new EventService(stores, config);
 | 
			
		||||
    const groupService = new GroupService(stores, config, eventService);
 | 
			
		||||
    const accessService = new AccessService(stores, config, groupService);
 | 
			
		||||
    const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        accessService,
 | 
			
		||||
    );
 | 
			
		||||
    const privateProjectChecker = createPrivateProjectChecker(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        config,
 | 
			
		||||
    );
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
    segmentService = new SegmentService(
 | 
			
		||||
        stores,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        config,
 | 
			
		||||
        eventService,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    service = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        segmentService,
 | 
			
		||||
        accessService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
    );
 | 
			
		||||
    segmentService = createSegmentService(db.rawDatabase, config);
 | 
			
		||||
 | 
			
		||||
    service = createFeatureToggleService(db.rawDatabase, config);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(async () => {
 | 
			
		||||
@ -462,40 +429,14 @@ test('If change requests are enabled, cannot change variants without going via C
 | 
			
		||||
        { name: featureName },
 | 
			
		||||
        'test-user',
 | 
			
		||||
    );
 | 
			
		||||
    const eventService = new EventService(stores, unleashConfig);
 | 
			
		||||
    const groupService = new GroupService(stores, unleashConfig, eventService);
 | 
			
		||||
    const accessService = new AccessService(
 | 
			
		||||
        stores,
 | 
			
		||||
        unleashConfig,
 | 
			
		||||
        groupService,
 | 
			
		||||
    );
 | 
			
		||||
    const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        accessService,
 | 
			
		||||
    );
 | 
			
		||||
    const privateProjectChecker = createPrivateProjectChecker(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        unleashConfig,
 | 
			
		||||
    );
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Force all feature flags on to make sure we have Change requests on
 | 
			
		||||
    const customFeatureService = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        {
 | 
			
		||||
    const customFeatureService = createFeatureToggleService(db.rawDatabase, {
 | 
			
		||||
        ...unleashConfig,
 | 
			
		||||
        flagResolver: {
 | 
			
		||||
            isEnabled: () => true,
 | 
			
		||||
        },
 | 
			
		||||
        },
 | 
			
		||||
        segmentService,
 | 
			
		||||
        accessService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
    );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const newVariant: IVariant = {
 | 
			
		||||
        name: 'cr-enabled',
 | 
			
		||||
@ -556,40 +497,14 @@ test('If CRs are protected for any environment in the project stops bulk update
 | 
			
		||||
        project.id,
 | 
			
		||||
        disabledEnv.name,
 | 
			
		||||
    );
 | 
			
		||||
    const eventService = new EventService(stores, unleashConfig);
 | 
			
		||||
    const groupService = new GroupService(stores, unleashConfig, eventService);
 | 
			
		||||
    const accessService = new AccessService(
 | 
			
		||||
        stores,
 | 
			
		||||
        unleashConfig,
 | 
			
		||||
        groupService,
 | 
			
		||||
    );
 | 
			
		||||
    const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        accessService,
 | 
			
		||||
    );
 | 
			
		||||
    const privateProjectChecker = createPrivateProjectChecker(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        unleashConfig,
 | 
			
		||||
    );
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // Force all feature flags on to make sure we have Change requests on
 | 
			
		||||
    const customFeatureService = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        {
 | 
			
		||||
    const customFeatureService = createFeatureToggleService(db.rawDatabase, {
 | 
			
		||||
        ...unleashConfig,
 | 
			
		||||
        flagResolver: {
 | 
			
		||||
            isEnabled: () => true,
 | 
			
		||||
        },
 | 
			
		||||
        },
 | 
			
		||||
        segmentService,
 | 
			
		||||
        accessService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
    );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const toggle = await service.createFeatureToggle(
 | 
			
		||||
        project.id,
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,6 @@ import { createTestConfig } from '../../config/test-config';
 | 
			
		||||
import dbInit, { ITestDb } from '../helpers/database-init';
 | 
			
		||||
import { IUnleashStores } from '../../../lib/types/stores';
 | 
			
		||||
import FeatureToggleService from '../../../lib/services/feature-toggle-service';
 | 
			
		||||
import { SegmentService } from '../../../lib/services/segment-service';
 | 
			
		||||
import { FeatureToggle, ISegment, WeightType } from '../../../lib/types/model';
 | 
			
		||||
import { PlaygroundFeatureSchema } from '../../../lib/openapi/spec/playground-feature-schema';
 | 
			
		||||
import { offlineUnleashClientNode } from '../../../lib/features/playground/offline-unleash-client.test';
 | 
			
		||||
@ -21,13 +20,12 @@ import { SdkContextSchema } from 'lib/openapi/spec/sdk-context-schema';
 | 
			
		||||
import { SegmentSchema } from 'lib/openapi/spec/segment-schema';
 | 
			
		||||
import { playgroundStrategyEvaluation } from '../../../lib/openapi/spec/playground-strategy-schema';
 | 
			
		||||
import { PlaygroundSegmentSchema } from 'lib/openapi/spec/playground-segment-schema';
 | 
			
		||||
import { GroupService } from '../../../lib/services/group-service';
 | 
			
		||||
import { AccessService } from '../../../lib/services/access-service';
 | 
			
		||||
import { ISegmentService } from '../../../lib/segments/segment-service-interface';
 | 
			
		||||
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model';
 | 
			
		||||
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker';
 | 
			
		||||
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model';
 | 
			
		||||
import { EventService } from '../../../lib/services';
 | 
			
		||||
import {
 | 
			
		||||
    createFeatureToggleService,
 | 
			
		||||
    createSegmentService,
 | 
			
		||||
} from '../../../lib/features';
 | 
			
		||||
 | 
			
		||||
let stores: IUnleashStores;
 | 
			
		||||
let db: ITestDb;
 | 
			
		||||
@ -39,38 +37,13 @@ beforeAll(async () => {
 | 
			
		||||
    const config = createTestConfig();
 | 
			
		||||
    db = await dbInit('playground_service_serial', config.getLogger);
 | 
			
		||||
    stores = db.stores;
 | 
			
		||||
    const eventService = new EventService(stores, config);
 | 
			
		||||
    const groupService = new GroupService(stores, config, eventService);
 | 
			
		||||
    const accessService = new AccessService(stores, config, groupService);
 | 
			
		||||
    const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        accessService,
 | 
			
		||||
    );
 | 
			
		||||
    const privateProjectChecker = createPrivateProjectChecker(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        config,
 | 
			
		||||
    );
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
    segmentService = new SegmentService(
 | 
			
		||||
        stores,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        config,
 | 
			
		||||
        eventService,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
    );
 | 
			
		||||
    segmentService = createSegmentService(db.rawDatabase, config);
 | 
			
		||||
 | 
			
		||||
    featureToggleService = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        segmentService,
 | 
			
		||||
        accessService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
    );
 | 
			
		||||
    featureToggleService = createFeatureToggleService(db.rawDatabase, config);
 | 
			
		||||
    service = new PlaygroundService(config, {
 | 
			
		||||
        featureToggleServiceV2: featureToggleService,
 | 
			
		||||
        segmentService,
 | 
			
		||||
 | 
			
		||||
@ -1,28 +1,21 @@
 | 
			
		||||
import dbInit, { ITestDb } from '../helpers/database-init';
 | 
			
		||||
import getLogger from '../../fixtures/no-logger';
 | 
			
		||||
import FeatureToggleService from '../../../lib/services/feature-toggle-service';
 | 
			
		||||
import { AccessService } from '../../../lib/services/access-service';
 | 
			
		||||
import ProjectService from '../../../lib/services/project-service';
 | 
			
		||||
import ProjectHealthService from '../../../lib/services/project-health-service';
 | 
			
		||||
import { createTestConfig } from '../../config/test-config';
 | 
			
		||||
import { IUnleashStores } from '../../../lib/types';
 | 
			
		||||
import { IUser } from '../../../lib/server-impl';
 | 
			
		||||
import { SegmentService } from '../../../lib/services/segment-service';
 | 
			
		||||
import { GroupService } from '../../../lib/services/group-service';
 | 
			
		||||
import { EventService, FavoritesService } from '../../../lib/services';
 | 
			
		||||
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model';
 | 
			
		||||
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker';
 | 
			
		||||
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model';
 | 
			
		||||
import { EventService } from '../../../lib/services';
 | 
			
		||||
import {
 | 
			
		||||
    createFeatureToggleService,
 | 
			
		||||
    createProjectService,
 | 
			
		||||
} from '../../../lib/features';
 | 
			
		||||
 | 
			
		||||
let stores: IUnleashStores;
 | 
			
		||||
let db: ITestDb;
 | 
			
		||||
let projectService;
 | 
			
		||||
let groupService;
 | 
			
		||||
let accessService;
 | 
			
		||||
let eventService: EventService;
 | 
			
		||||
let projectHealthService;
 | 
			
		||||
let featureToggleService;
 | 
			
		||||
let favoritesService;
 | 
			
		||||
let user: IUser;
 | 
			
		||||
 | 
			
		||||
beforeAll(async () => {
 | 
			
		||||
@ -34,47 +27,10 @@ beforeAll(async () => {
 | 
			
		||||
        email: 'test@getunleash.io',
 | 
			
		||||
    });
 | 
			
		||||
    eventService = new EventService(stores, config);
 | 
			
		||||
    groupService = new GroupService(stores, config, eventService);
 | 
			
		||||
    accessService = new AccessService(stores, config, groupService);
 | 
			
		||||
    const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        accessService,
 | 
			
		||||
    );
 | 
			
		||||
    const privateProjectChecker = createPrivateProjectChecker(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        config,
 | 
			
		||||
    );
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
    featureToggleService = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        new SegmentService(
 | 
			
		||||
            stores,
 | 
			
		||||
            changeRequestAccessReadModel,
 | 
			
		||||
            config,
 | 
			
		||||
            eventService,
 | 
			
		||||
            privateProjectChecker,
 | 
			
		||||
        ),
 | 
			
		||||
        accessService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
    );
 | 
			
		||||
    favoritesService = new FavoritesService(stores, config, eventService);
 | 
			
		||||
 | 
			
		||||
    projectService = new ProjectService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        accessService,
 | 
			
		||||
        featureToggleService,
 | 
			
		||||
        groupService,
 | 
			
		||||
        favoritesService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
    );
 | 
			
		||||
    featureToggleService = createFeatureToggleService(db.rawDatabase, config);
 | 
			
		||||
 | 
			
		||||
    projectService = createProjectService(db.rawDatabase, config);
 | 
			
		||||
    projectHealthService = new ProjectHealthService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
 | 
			
		||||
@ -9,25 +9,23 @@ import { RoleName } from '../../../lib/types/model';
 | 
			
		||||
import { randomId } from '../../../lib/util/random-id';
 | 
			
		||||
import EnvironmentService from '../../../lib/services/environment-service';
 | 
			
		||||
import IncompatibleProjectError from '../../../lib/error/incompatible-project-error';
 | 
			
		||||
import { SegmentService } from '../../../lib/services/segment-service';
 | 
			
		||||
import { GroupService } from '../../../lib/services/group-service';
 | 
			
		||||
import { EventService, FavoritesService } from '../../../lib/services';
 | 
			
		||||
import { EventService } from '../../../lib/services';
 | 
			
		||||
import { FeatureEnvironmentEvent } from '../../../lib/types/events';
 | 
			
		||||
import { addDays, subDays } from 'date-fns';
 | 
			
		||||
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model';
 | 
			
		||||
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker';
 | 
			
		||||
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model';
 | 
			
		||||
import {
 | 
			
		||||
    createAccessService,
 | 
			
		||||
    createFeatureToggleService,
 | 
			
		||||
    createProjectService,
 | 
			
		||||
} from '../../../lib/features';
 | 
			
		||||
 | 
			
		||||
let stores;
 | 
			
		||||
let db: ITestDb;
 | 
			
		||||
 | 
			
		||||
let projectService: ProjectService;
 | 
			
		||||
let groupService: GroupService;
 | 
			
		||||
let accessService: AccessService;
 | 
			
		||||
let eventService: EventService;
 | 
			
		||||
let environmentService: EnvironmentService;
 | 
			
		||||
let featureToggleService: FeatureToggleService;
 | 
			
		||||
let favoritesService: FavoritesService;
 | 
			
		||||
let user;
 | 
			
		||||
 | 
			
		||||
const isProjectUser = async (
 | 
			
		||||
@ -55,48 +53,12 @@ beforeAll(async () => {
 | 
			
		||||
        },
 | 
			
		||||
    });
 | 
			
		||||
    eventService = new EventService(stores, config);
 | 
			
		||||
    groupService = new GroupService(stores, config, eventService);
 | 
			
		||||
    accessService = new AccessService(stores, config, groupService);
 | 
			
		||||
    const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        accessService,
 | 
			
		||||
    );
 | 
			
		||||
    const privateProjectChecker = createPrivateProjectChecker(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
        config,
 | 
			
		||||
    );
 | 
			
		||||
    const dependentFeaturesReadModel = new DependentFeaturesReadModel(
 | 
			
		||||
        db.rawDatabase,
 | 
			
		||||
    );
 | 
			
		||||
    featureToggleService = new FeatureToggleService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        new SegmentService(
 | 
			
		||||
            stores,
 | 
			
		||||
            changeRequestAccessReadModel,
 | 
			
		||||
            config,
 | 
			
		||||
            eventService,
 | 
			
		||||
            privateProjectChecker,
 | 
			
		||||
        ),
 | 
			
		||||
        accessService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        changeRequestAccessReadModel,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
        dependentFeaturesReadModel,
 | 
			
		||||
    );
 | 
			
		||||
    accessService = createAccessService(db.rawDatabase, config);
 | 
			
		||||
 | 
			
		||||
    featureToggleService = createFeatureToggleService(db.rawDatabase, config);
 | 
			
		||||
 | 
			
		||||
    favoritesService = new FavoritesService(stores, config, eventService);
 | 
			
		||||
    environmentService = new EnvironmentService(stores, config);
 | 
			
		||||
    projectService = new ProjectService(
 | 
			
		||||
        stores,
 | 
			
		||||
        config,
 | 
			
		||||
        accessService,
 | 
			
		||||
        featureToggleService,
 | 
			
		||||
        groupService,
 | 
			
		||||
        favoritesService,
 | 
			
		||||
        eventService,
 | 
			
		||||
        privateProjectChecker,
 | 
			
		||||
    );
 | 
			
		||||
    projectService = createProjectService(db.rawDatabase, config);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
afterAll(async () => {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user