1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-09 01:17:06 +02:00

feat: copy feature with parent (#4918)

This commit is contained in:
Mateusz Kwasniewski 2023-10-04 12:20:27 +02:00 committed by GitHub
parent 5141d9db67
commit 257414424d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 140 additions and 346 deletions

View File

@ -84,7 +84,7 @@ export const AddDependencyDialogue = ({
secondaryButtonText='Cancel' secondaryButtonText='Cancel'
> >
<Box> <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. feature is enabled in the same environment.
<br /> <br />
<br /> <br />

View File

@ -22,6 +22,32 @@ export class DependentFeaturesService {
this.eventService = eventService; 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( async upsertFeatureDependency(
{ child, projectId }: { child: string; projectId: string }, { child, projectId }: { child: string; projectId: string },
dependentFeature: CreateDependentFeatureSchema, dependentFeature: CreateDependentFeatureSchema,

View File

@ -48,6 +48,10 @@ import { DependentFeaturesReadModel } from '../dependent-features/dependent-feat
import { FakeDependentFeaturesReadModel } from '../dependent-features/fake-dependent-features-read-model'; import { FakeDependentFeaturesReadModel } from '../dependent-features/fake-dependent-features-read-model';
import FeatureTagStore from '../../db/feature-tag-store'; import FeatureTagStore from '../../db/feature-tag-store';
import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store'; import FakeFeatureTagStore from '../../../test/fixtures/fake-feature-tag-store';
import {
createDependentFeaturesService,
createFakeDependentFeaturesService,
} from '../dependent-features/createDependentFeaturesService';
export const createFeatureToggleService = ( export const createFeatureToggleService = (
db: Db, db: Db,
@ -115,6 +119,8 @@ export const createFeatureToggleService = (
const dependentFeaturesReadModel = new DependentFeaturesReadModel(db); const dependentFeaturesReadModel = new DependentFeaturesReadModel(db);
const dependentFeaturesService = createDependentFeaturesService(db, config);
const featureToggleService = new FeatureToggleService( const featureToggleService = new FeatureToggleService(
{ {
featureStrategiesStore, featureStrategiesStore,
@ -133,6 +139,7 @@ export const createFeatureToggleService = (
changeRequestAccessReadModel, changeRequestAccessReadModel,
privateProjectChecker, privateProjectChecker,
dependentFeaturesReadModel, dependentFeaturesReadModel,
dependentFeaturesService,
); );
return featureToggleService; return featureToggleService;
}; };
@ -173,6 +180,7 @@ export const createFakeFeatureToggleService = (
const changeRequestAccessReadModel = createFakeChangeRequestAccessService(); const changeRequestAccessReadModel = createFakeChangeRequestAccessService();
const fakePrivateProjectChecker = createFakePrivateProjectChecker(); const fakePrivateProjectChecker = createFakePrivateProjectChecker();
const dependentFeaturesReadModel = new FakeDependentFeaturesReadModel(); const dependentFeaturesReadModel = new FakeDependentFeaturesReadModel();
const dependentFeaturesService = createFakeDependentFeaturesService(config);
const featureToggleService = new FeatureToggleService( const featureToggleService = new FeatureToggleService(
{ {
featureStrategiesStore, featureStrategiesStore,
@ -191,6 +199,7 @@ export const createFakeFeatureToggleService = (
changeRequestAccessReadModel, changeRequestAccessReadModel,
fakePrivateProjectChecker, fakePrivateProjectChecker,
dependentFeaturesReadModel, dependentFeaturesReadModel,
dependentFeaturesService,
); );
return featureToggleService; return featureToggleService;
}; };

View File

@ -13,6 +13,7 @@ import { IPrivateProjectChecker } from '../features/private-project/privateProje
import { IDependentFeaturesReadModel } from '../features/dependent-features/dependent-features-read-model-type'; import { IDependentFeaturesReadModel } from '../features/dependent-features/dependent-features-read-model-type';
import EventService from './event-service'; import EventService from './event-service';
import FakeFeatureTagStore from '../../test/fixtures/fake-feature-tag-store'; 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 () => { test('Should only store events for potentially stale on', async () => {
expect.assertions(2); expect.assertions(2);
@ -64,6 +65,7 @@ test('Should only store events for potentially stale on', async () => {
{} as IChangeRequestAccessReadModel, {} as IChangeRequestAccessReadModel,
{} as IPrivateProjectChecker, {} as IPrivateProjectChecker,
{} as IDependentFeaturesReadModel, {} as IDependentFeaturesReadModel,
{} as DependentFeaturesService,
); );
await featureToggleService.updatePotentiallyStaleFeatures(); await featureToggleService.updatePotentiallyStaleFeatures();

View File

@ -99,6 +99,7 @@ import { checkFeatureFlagNamesAgainstPattern } from '../features/feature-naming-
import { IPrivateProjectChecker } from '../features/private-project/privateProjectCheckerType'; import { IPrivateProjectChecker } from '../features/private-project/privateProjectCheckerType';
import { IDependentFeaturesReadModel } from '../features/dependent-features/dependent-features-read-model-type'; import { IDependentFeaturesReadModel } from '../features/dependent-features/dependent-features-read-model-type';
import EventService from './event-service'; import EventService from './event-service';
import { DependentFeaturesService } from '../features/dependent-features/dependent-features-service';
interface IFeatureContext { interface IFeatureContext {
featureName: string; featureName: string;
@ -162,6 +163,8 @@ class FeatureToggleService {
private dependentFeaturesReadModel: IDependentFeaturesReadModel; private dependentFeaturesReadModel: IDependentFeaturesReadModel;
private dependentFeaturesService: DependentFeaturesService;
constructor( constructor(
{ {
featureStrategiesStore, featureStrategiesStore,
@ -193,6 +196,7 @@ class FeatureToggleService {
changeRequestAccessReadModel: IChangeRequestAccessReadModel, changeRequestAccessReadModel: IChangeRequestAccessReadModel,
privateProjectChecker: IPrivateProjectChecker, privateProjectChecker: IPrivateProjectChecker,
dependentFeaturesReadModel: IDependentFeaturesReadModel, dependentFeaturesReadModel: IDependentFeaturesReadModel,
dependentFeaturesService: DependentFeaturesService,
) { ) {
this.logger = getLogger('services/feature-toggle-service.ts'); this.logger = getLogger('services/feature-toggle-service.ts');
this.featureStrategiesStore = featureStrategiesStore; this.featureStrategiesStore = featureStrategiesStore;
@ -210,6 +214,7 @@ class FeatureToggleService {
this.changeRequestAccessReadModel = changeRequestAccessReadModel; this.changeRequestAccessReadModel = changeRequestAccessReadModel;
this.privateProjectChecker = privateProjectChecker; this.privateProjectChecker = privateProjectChecker;
this.dependentFeaturesReadModel = dependentFeaturesReadModel; this.dependentFeaturesReadModel = dependentFeaturesReadModel;
this.dependentFeaturesService = dependentFeaturesService;
} }
async validateFeaturesContext( 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; return created;
} }

View File

@ -233,6 +233,13 @@ export const createServices = (
config, config,
privateProjectChecker, privateProjectChecker,
); );
const dependentFeaturesService = db
? createDependentFeaturesService(db, config)
: createFakeDependentFeaturesService(config);
const transactionalDependentFeaturesService = (txDb: Knex.Transaction) =>
createDependentFeaturesService(txDb, config);
const featureToggleServiceV2 = new FeatureToggleService( const featureToggleServiceV2 = new FeatureToggleService(
stores, stores,
config, config,
@ -242,6 +249,7 @@ export const createServices = (
changeRequestAccessReadModel, changeRequestAccessReadModel,
privateProjectChecker, privateProjectChecker,
dependentFeaturesReadModel, dependentFeaturesReadModel,
dependentFeaturesService,
); );
const environmentService = new EnvironmentService(stores, config); const environmentService = new EnvironmentService(stores, config);
const featureTagService = new FeatureTagService( const featureTagService = new FeatureTagService(
@ -327,12 +335,6 @@ export const createServices = (
const eventAnnouncerService = new EventAnnouncerService(stores, config); const eventAnnouncerService = new EventAnnouncerService(stores, config);
const dependentFeaturesService = db
? createDependentFeaturesService(db, config)
: createFakeDependentFeaturesService(config);
const transactionalDependentFeaturesService = (txDb: Knex.Transaction) =>
createDependentFeaturesService(txDb, config);
return { return {
accessService, accessService,
accountService, accountService,

View File

@ -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 () => { test('Can get features for project', async () => {
await app.request await app.request
.post('/api/admin/projects/default/features') .post('/api/admin/projects/default/features')

View File

@ -13,25 +13,19 @@ import {
IUnleashStores, IUnleashStores,
IUserAccessOverview, IUserAccessOverview,
} from '../../../lib/types'; } 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 { createTestConfig } from '../../config/test-config';
import { DEFAULT_PROJECT } from '../../../lib/types/project'; import { DEFAULT_PROJECT } from '../../../lib/types/project';
import { ALL_PROJECTS } from '../../../lib/util/constants'; import { ALL_PROJECTS } from '../../../lib/util/constants';
import { SegmentService } from '../../../lib/services/segment-service'; import {
import { GroupService } from '../../../lib/services/group-service'; createAccessService,
import { EventService, FavoritesService } from '../../../lib/services'; createFeatureToggleService,
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model'; createProjectService,
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker'; } from '../../../lib/features';
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model';
let db: ITestDb; let db: ITestDb;
let stores: IUnleashStores; let stores: IUnleashStores;
let accessService: AccessService; let accessService: AccessService;
let eventService: EventService;
let groupService: GroupService;
let featureToggleService; let featureToggleService;
let favoritesService;
let projectService; let projectService;
let editorUser; let editorUser;
let editorRole; let editorRole;
@ -238,51 +232,14 @@ beforeAll(async () => {
// @ts-ignore // @ts-ignore
experimental: { environments: { enabled: true } }, experimental: { environments: { enabled: true } },
}); });
eventService = new EventService(stores, config); accessService = createAccessService(db.rawDatabase, config);
groupService = new GroupService(stores, { getLogger }, eventService);
accessService = new AccessService(stores, config, groupService);
const roles = await accessService.getRootRoles(); const roles = await accessService.getRootRoles();
editorRole = roles.find((r) => r.name === RoleName.EDITOR); editorRole = roles.find((r) => r.name === RoleName.EDITOR);
adminRole = roles.find((r) => r.name === RoleName.ADMIN); adminRole = roles.find((r) => r.name === RoleName.ADMIN);
readRole = roles.find((r) => r.name === RoleName.VIEWER); readRole = roles.find((r) => r.name === RoleName.VIEWER);
const changeRequestAccessReadModel = new ChangeRequestAccessReadModel(
db.rawDatabase, featureToggleService = createFeatureToggleService(db.rawDatabase, config);
accessService, projectService = createProjectService(db.rawDatabase, config);
);
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,
);
editorUser = await createUser(editorRole.id); editorUser = await createUser(editorRole.id);

View File

@ -6,20 +6,13 @@ import { ApiTokenType, IApiToken } from '../../../lib/types/models/api-token';
import { DEFAULT_ENV } from '../../../lib/util/constants'; import { DEFAULT_ENV } from '../../../lib/util/constants';
import { addDays, subDays } from 'date-fns'; import { addDays, subDays } from 'date-fns';
import ProjectService from '../../../lib/services/project-service'; import ProjectService from '../../../lib/services/project-service';
import FeatureToggleService from '../../../lib/services/feature-toggle-service'; import { EventService } from '../../../lib/services';
import { AccessService } from '../../../lib/services/access-service'; import { createProjectService } from '../../../lib/features';
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';
let db; let db;
let stores; let stores;
let apiTokenService: ApiTokenService; let apiTokenService: ApiTokenService;
let projectService: ProjectService; let projectService: ProjectService;
let favoritesService: FavoritesService;
beforeAll(async () => { beforeAll(async () => {
const config = createTestConfig({ const config = createTestConfig({
@ -28,35 +21,6 @@ beforeAll(async () => {
db = await dbInit('api_token_service_serial', getLogger); db = await dbInit('api_token_service_serial', getLogger);
stores = db.stores; stores = db.stores;
const eventService = new EventService(stores, config); 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 = { const project = {
id: 'test-project', id: 'test-project',
name: 'Test Project', name: 'Test Project',
@ -68,17 +32,7 @@ beforeAll(async () => {
name: 'Some Name', name: 'Some Name',
email: 'test@getunleash.io', email: 'test@getunleash.io',
}); });
favoritesService = new FavoritesService(stores, config, eventService); projectService = createProjectService(db.rawDatabase, config);
projectService = new ProjectService(
stores,
config,
accessService,
featureToggleService,
groupService,
favoritesService,
eventService,
privateProjectChecker,
);
await projectService.createProject(project, user); await projectService.createProject(project, user);

View File

@ -2,12 +2,6 @@ import FeatureToggleService from '../../../lib/services/feature-toggle-service';
import { createTestConfig } from '../../config/test-config'; import { createTestConfig } from '../../config/test-config';
import dbInit from '../helpers/database-init'; import dbInit from '../helpers/database-init';
import { DEFAULT_ENV } from '../../../lib/util'; import { DEFAULT_ENV } from '../../../lib/util';
import {
AccessService,
EventService,
GroupService,
SegmentService,
} from '../../../lib/services';
import { FeatureStrategySchema } from '../../../lib/openapi'; import { FeatureStrategySchema } from '../../../lib/openapi';
import User from '../../../lib/types/user'; import User from '../../../lib/types/user';
import { import {
@ -23,9 +17,10 @@ import {
PermissionError, PermissionError,
} from '../../../lib/error'; } from '../../../lib/error';
import { ISegmentService } from '../../../lib/segments/segment-service-interface'; import { ISegmentService } from '../../../lib/segments/segment-service-interface';
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model'; import {
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker'; createFeatureToggleService,
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model'; createSegmentService,
} from '../../../lib/features';
let stores: IUnleashStores; let stores: IUnleashStores;
let db; let db;
@ -54,38 +49,10 @@ beforeAll(async () => {
); );
unleashConfig = config; unleashConfig = config;
stores = db.stores; 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( segmentService = createSegmentService(db.rawDatabase, config);
stores,
config, service = createFeatureToggleService(db.rawDatabase, config);
segmentService,
accessService,
eventService,
changeRequestAccessReadModel,
privateProjectChecker,
dependentFeaturesReadModel,
);
}); });
afterAll(async () => { afterAll(async () => {
@ -462,40 +429,14 @@ test('If change requests are enabled, cannot change variants without going via C
{ name: featureName }, { name: featureName },
'test-user', '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 // Force all feature flags on to make sure we have Change requests on
const customFeatureService = new FeatureToggleService( const customFeatureService = createFeatureToggleService(db.rawDatabase, {
stores, ...unleashConfig,
{ flagResolver: {
...unleashConfig, isEnabled: () => true,
flagResolver: {
isEnabled: () => true,
},
}, },
segmentService, });
accessService,
eventService,
changeRequestAccessReadModel,
privateProjectChecker,
dependentFeaturesReadModel,
);
const newVariant: IVariant = { const newVariant: IVariant = {
name: 'cr-enabled', name: 'cr-enabled',
@ -556,40 +497,14 @@ test('If CRs are protected for any environment in the project stops bulk update
project.id, project.id,
disabledEnv.name, 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 // Force all feature flags on to make sure we have Change requests on
const customFeatureService = new FeatureToggleService( const customFeatureService = createFeatureToggleService(db.rawDatabase, {
stores, ...unleashConfig,
{ flagResolver: {
...unleashConfig, isEnabled: () => true,
flagResolver: {
isEnabled: () => true,
},
}, },
segmentService, });
accessService,
eventService,
changeRequestAccessReadModel,
privateProjectChecker,
dependentFeaturesReadModel,
);
const toggle = await service.createFeatureToggle( const toggle = await service.createFeatureToggle(
project.id, project.id,

View File

@ -12,7 +12,6 @@ import { createTestConfig } from '../../config/test-config';
import dbInit, { ITestDb } from '../helpers/database-init'; import dbInit, { ITestDb } from '../helpers/database-init';
import { IUnleashStores } from '../../../lib/types/stores'; import { IUnleashStores } from '../../../lib/types/stores';
import FeatureToggleService from '../../../lib/services/feature-toggle-service'; import FeatureToggleService from '../../../lib/services/feature-toggle-service';
import { SegmentService } from '../../../lib/services/segment-service';
import { FeatureToggle, ISegment, WeightType } from '../../../lib/types/model'; import { FeatureToggle, ISegment, WeightType } from '../../../lib/types/model';
import { PlaygroundFeatureSchema } from '../../../lib/openapi/spec/playground-feature-schema'; import { PlaygroundFeatureSchema } from '../../../lib/openapi/spec/playground-feature-schema';
import { offlineUnleashClientNode } from '../../../lib/features/playground/offline-unleash-client.test'; 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 { SegmentSchema } from 'lib/openapi/spec/segment-schema';
import { playgroundStrategyEvaluation } from '../../../lib/openapi/spec/playground-strategy-schema'; import { playgroundStrategyEvaluation } from '../../../lib/openapi/spec/playground-strategy-schema';
import { PlaygroundSegmentSchema } from 'lib/openapi/spec/playground-segment-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 { 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 { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker';
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model'; import {
import { EventService } from '../../../lib/services'; createFeatureToggleService,
createSegmentService,
} from '../../../lib/features';
let stores: IUnleashStores; let stores: IUnleashStores;
let db: ITestDb; let db: ITestDb;
@ -39,38 +37,13 @@ beforeAll(async () => {
const config = createTestConfig(); const config = createTestConfig();
db = await dbInit('playground_service_serial', config.getLogger); db = await dbInit('playground_service_serial', config.getLogger);
stores = db.stores; 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( const privateProjectChecker = createPrivateProjectChecker(
db.rawDatabase, db.rawDatabase,
config, config,
); );
const dependentFeaturesReadModel = new DependentFeaturesReadModel( segmentService = createSegmentService(db.rawDatabase, config);
db.rawDatabase,
);
segmentService = new SegmentService(
stores,
changeRequestAccessReadModel,
config,
eventService,
privateProjectChecker,
);
featureToggleService = new FeatureToggleService( featureToggleService = createFeatureToggleService(db.rawDatabase, config);
stores,
config,
segmentService,
accessService,
eventService,
changeRequestAccessReadModel,
privateProjectChecker,
dependentFeaturesReadModel,
);
service = new PlaygroundService(config, { service = new PlaygroundService(config, {
featureToggleServiceV2: featureToggleService, featureToggleServiceV2: featureToggleService,
segmentService, segmentService,

View File

@ -1,28 +1,21 @@
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 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 ProjectHealthService from '../../../lib/services/project-health-service';
import { createTestConfig } from '../../config/test-config'; import { createTestConfig } from '../../config/test-config';
import { IUnleashStores } from '../../../lib/types'; import { IUnleashStores } from '../../../lib/types';
import { IUser } from '../../../lib/server-impl'; import { IUser } from '../../../lib/server-impl';
import { SegmentService } from '../../../lib/services/segment-service'; import { EventService } from '../../../lib/services';
import { GroupService } from '../../../lib/services/group-service'; import {
import { EventService, FavoritesService } from '../../../lib/services'; createFeatureToggleService,
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model'; createProjectService,
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker'; } from '../../../lib/features';
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model';
let stores: IUnleashStores; let stores: IUnleashStores;
let db: ITestDb; let db: ITestDb;
let projectService; let projectService;
let groupService;
let accessService;
let eventService: EventService; let eventService: EventService;
let projectHealthService; let projectHealthService;
let featureToggleService; let featureToggleService;
let favoritesService;
let user: IUser; let user: IUser;
beforeAll(async () => { beforeAll(async () => {
@ -34,47 +27,10 @@ beforeAll(async () => {
email: 'test@getunleash.io', email: 'test@getunleash.io',
}); });
eventService = new EventService(stores, config); 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( featureToggleService = createFeatureToggleService(db.rawDatabase, config);
stores,
config, projectService = createProjectService(db.rawDatabase, config);
accessService,
featureToggleService,
groupService,
favoritesService,
eventService,
privateProjectChecker,
);
projectHealthService = new ProjectHealthService( projectHealthService = new ProjectHealthService(
stores, stores,
config, config,

View File

@ -9,25 +9,23 @@ import { RoleName } from '../../../lib/types/model';
import { randomId } from '../../../lib/util/random-id'; import { randomId } from '../../../lib/util/random-id';
import EnvironmentService from '../../../lib/services/environment-service'; import EnvironmentService from '../../../lib/services/environment-service';
import IncompatibleProjectError from '../../../lib/error/incompatible-project-error'; import IncompatibleProjectError from '../../../lib/error/incompatible-project-error';
import { SegmentService } from '../../../lib/services/segment-service'; import { EventService } from '../../../lib/services';
import { GroupService } from '../../../lib/services/group-service';
import { EventService, FavoritesService } from '../../../lib/services';
import { FeatureEnvironmentEvent } from '../../../lib/types/events'; import { FeatureEnvironmentEvent } from '../../../lib/types/events';
import { addDays, subDays } from 'date-fns'; import { addDays, subDays } from 'date-fns';
import { ChangeRequestAccessReadModel } from '../../../lib/features/change-request-access-service/sql-change-request-access-read-model'; import {
import { createPrivateProjectChecker } from '../../../lib/features/private-project/createPrivateProjectChecker'; createAccessService,
import { DependentFeaturesReadModel } from '../../../lib/features/dependent-features/dependent-features-read-model'; createFeatureToggleService,
createProjectService,
} from '../../../lib/features';
let stores; let stores;
let db: ITestDb; let db: ITestDb;
let projectService: ProjectService; let projectService: ProjectService;
let groupService: GroupService;
let accessService: AccessService; let accessService: AccessService;
let eventService: EventService; let eventService: EventService;
let environmentService: EnvironmentService; let environmentService: EnvironmentService;
let featureToggleService: FeatureToggleService; let featureToggleService: FeatureToggleService;
let favoritesService: FavoritesService;
let user; let user;
const isProjectUser = async ( const isProjectUser = async (
@ -55,48 +53,12 @@ beforeAll(async () => {
}, },
}); });
eventService = new EventService(stores, config); eventService = new EventService(stores, config);
groupService = new GroupService(stores, config, eventService); accessService = createAccessService(db.rawDatabase, config);
accessService = new AccessService(stores, config, groupService);
const changeRequestAccessReadModel = new ChangeRequestAccessReadModel( featureToggleService = createFeatureToggleService(db.rawDatabase, config);
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);
environmentService = new EnvironmentService(stores, config); environmentService = new EnvironmentService(stores, config);
projectService = new ProjectService( projectService = createProjectService(db.rawDatabase, config);
stores,
config,
accessService,
featureToggleService,
groupService,
favoritesService,
eventService,
privateProjectChecker,
);
}); });
afterAll(async () => { afterAll(async () => {