diff --git a/frontend/src/component/feature/Dependencies/AddDependencyDialogue.tsx b/frontend/src/component/feature/Dependencies/AddDependencyDialogue.tsx index acabd1f083..e0a8b6f838 100644 --- a/frontend/src/component/feature/Dependencies/AddDependencyDialogue.tsx +++ b/frontend/src/component/feature/Dependencies/AddDependencyDialogue.tsx @@ -84,7 +84,7 @@ export const AddDependencyDialogue = ({ secondaryButtonText='Cancel' > - 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.

diff --git a/src/lib/features/dependent-features/dependent-features-service.ts b/src/lib/features/dependent-features/dependent-features-service.ts index 1afc08d770..7c891aeb77 100644 --- a/src/lib/features/dependent-features/dependent-features-service.ts +++ b/src/lib/features/dependent-features/dependent-features-service.ts @@ -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, diff --git a/src/lib/features/feature-toggle/createFeatureToggleService.ts b/src/lib/features/feature-toggle/createFeatureToggleService.ts index 50ce9098dd..aa6af416f4 100644 --- a/src/lib/features/feature-toggle/createFeatureToggleService.ts +++ b/src/lib/features/feature-toggle/createFeatureToggleService.ts @@ -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; }; diff --git a/src/lib/services/feature-service-potentially-stale.test.ts b/src/lib/services/feature-service-potentially-stale.test.ts index 2a7a9f9dfa..551074aeca 100644 --- a/src/lib/services/feature-service-potentially-stale.test.ts +++ b/src/lib/services/feature-service-potentially-stale.test.ts @@ -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(); diff --git a/src/lib/services/feature-toggle-service.ts b/src/lib/services/feature-toggle-service.ts index 7dec5526fb..f4aef31040 100644 --- a/src/lib/services/feature-toggle-service.ts +++ b/src/lib/services/feature-toggle-service.ts @@ -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; } diff --git a/src/lib/services/index.ts b/src/lib/services/index.ts index c81e21f768..38c025f45f 100644 --- a/src/lib/services/index.ts +++ b/src/lib/services/index.ts @@ -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, diff --git a/src/test/e2e/api/admin/project/features.e2e.test.ts b/src/test/e2e/api/admin/project/features.e2e.test.ts index da3635e723..2ba3d3046f 100644 --- a/src/test/e2e/api/admin/project/features.e2e.test.ts +++ b/src/test/e2e/api/admin/project/features.e2e.test.ts @@ -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') diff --git a/src/test/e2e/services/access-service.e2e.test.ts b/src/test/e2e/services/access-service.e2e.test.ts index 01a6e81f0f..b28b279863 100644 --- a/src/test/e2e/services/access-service.e2e.test.ts +++ b/src/test/e2e/services/access-service.e2e.test.ts @@ -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); diff --git a/src/test/e2e/services/api-token-service.e2e.test.ts b/src/test/e2e/services/api-token-service.e2e.test.ts index 30468e3ce9..0e131a8969 100644 --- a/src/test/e2e/services/api-token-service.e2e.test.ts +++ b/src/test/e2e/services/api-token-service.e2e.test.ts @@ -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); diff --git a/src/test/e2e/services/feature-toggle-service-v2.e2e.test.ts b/src/test/e2e/services/feature-toggle-service-v2.e2e.test.ts index 724a2b1b90..624675a705 100644 --- a/src/test/e2e/services/feature-toggle-service-v2.e2e.test.ts +++ b/src/test/e2e/services/feature-toggle-service-v2.e2e.test.ts @@ -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, - { - ...unleashConfig, - flagResolver: { - isEnabled: () => true, - }, + 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, - { - ...unleashConfig, - flagResolver: { - isEnabled: () => true, - }, + const customFeatureService = createFeatureToggleService(db.rawDatabase, { + ...unleashConfig, + flagResolver: { + isEnabled: () => true, }, - segmentService, - accessService, - eventService, - changeRequestAccessReadModel, - privateProjectChecker, - dependentFeaturesReadModel, - ); + }); const toggle = await service.createFeatureToggle( project.id, diff --git a/src/test/e2e/services/playground-service.test.ts b/src/test/e2e/services/playground-service.test.ts index dcea031d30..cc0d31a89b 100644 --- a/src/test/e2e/services/playground-service.test.ts +++ b/src/test/e2e/services/playground-service.test.ts @@ -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, diff --git a/src/test/e2e/services/project-health-service.e2e.test.ts b/src/test/e2e/services/project-health-service.e2e.test.ts index 9abefb5219..be6de7e836 100644 --- a/src/test/e2e/services/project-health-service.e2e.test.ts +++ b/src/test/e2e/services/project-health-service.e2e.test.ts @@ -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, diff --git a/src/test/e2e/services/project-service.e2e.test.ts b/src/test/e2e/services/project-service.e2e.test.ts index 5a7ec4aa13..d539ecab86 100644 --- a/src/test/e2e/services/project-service.e2e.test.ts +++ b/src/test/e2e/services/project-service.e2e.test.ts @@ -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 () => {