From aa4ecdfad57139b2ec64ac123869b14bf4a95fb5 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Mon, 8 May 2023 10:41:55 +0200 Subject: [PATCH] fix: import tags (#3709) --- .../export-import-service.ts | 18 ++++--- .../export-import.e2e.test.ts | 51 +++++++++++++++++++ 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/lib/features/export-import-toggles/export-import-service.ts b/src/lib/features/export-import-toggles/export-import-service.ts index 63deb7b41b..f007caab59 100644 --- a/src/lib/features/export-import-toggles/export-import-service.ts +++ b/src/lib/features/export-import-toggles/export-import-service.ts @@ -168,7 +168,7 @@ export default class ExportImportService { const errors = ImportValidationMessages.compileErrors( dto.project, unsupportedStrategies, - unsupportedContextFields, + unsupportedContextFields || [], [], otherProjectFeatures, false, @@ -225,7 +225,7 @@ export default class ExportImportService { private async importToggleStatuses(dto: ImportTogglesSchema, user: User) { await Promise.all( - dto.data.featureEnvironments?.map((featureEnvironment) => + (dto.data.featureEnvironments || []).map((featureEnvironment) => this.featureToggleService.updateEnabled( dto.project, featureEnvironment.name, @@ -279,15 +279,17 @@ export default class ExportImportService { await this.importTogglesStore.deleteTagsForFeatures( dto.data.features.map((feature) => feature.name), ); - return Promise.all( - dto.data.featureTags?.map((tag) => - this.featureTagService.addTag( + + const featureTags = dto.data.featureTags || []; + for (const tag of featureTags) { + if (tag.tagType) { + await this.featureTagService.addTag( tag.featureName, { type: tag.tagType, value: tag.tagValue }, extractUsernameFromUser(user), - ), - ), - ); + ); + } + } } private async importContextFields(dto: ImportTogglesSchema, user: User) { diff --git a/src/lib/features/export-import-toggles/export-import.e2e.test.ts b/src/lib/features/export-import-toggles/export-import.e2e.test.ts index 924fc8eaa2..7467bbc963 100644 --- a/src/lib/features/export-import-toggles/export-import.e2e.test.ts +++ b/src/lib/features/export-import-toggles/export-import.e2e.test.ts @@ -14,6 +14,7 @@ import { IProjectStore, ISegment, IStrategyConfig, + ITagStore, IVariant, } from '../../types'; import { DEFAULT_ENV } from '../../util'; @@ -33,6 +34,7 @@ let environmentStore: IEnvironmentStore; let contextFieldStore: IContextFieldStore; let projectStore: IProjectStore; let toggleStore: IFeatureToggleStore; +let tagStore: ITagStore; const defaultStrategy: IStrategyConfig = { name: 'default', @@ -150,6 +152,7 @@ beforeAll(async () => { projectStore = db.stores.projectStore; contextFieldStore = db.stores.contextFieldStore; toggleStore = db.stores.featureToggleStore; + tagStore = db.stores.tagStore; }); beforeEach(async () => { @@ -157,6 +160,7 @@ beforeEach(async () => { await toggleStore.deleteAll(); await projectStore.deleteAll(); await environmentStore.deleteAll(); + await tagStore.deleteAll(); await contextFieldStore.deleteAll(); await app.createContextField({ name: 'appName' }); @@ -488,6 +492,10 @@ const exportedFeature: ImportTogglesSchema['data']['features'][0] = { project: 'old_project', name: 'first_feature', }; +const anotherExportedFeature: ImportTogglesSchema['data']['features'][0] = { + project: 'old_project', + name: 'second_feature', +}; const constraints: ImportTogglesSchema['data']['featureStrategies'][0]['constraints'] = [ { @@ -558,6 +566,31 @@ const defaultImportPayload: ImportTogglesSchema = { environment: DEFAULT_ENV, }; +const importWithMultipleFeatures: ImportTogglesSchema = { + data: { + features: [exportedFeature, anotherExportedFeature], + featureStrategies: [], + featureEnvironments: [], + featureTags: [ + { + featureName: exportedFeature.name, + tagType: 'simple', + tagValue: 'tag1', + }, + { + featureName: anotherExportedFeature.name, + tagType: 'simple', + tagValue: 'tag1', + }, + ], + tagTypes, + contextFields: [], + segments: [], + }, + project: DEFAULT_PROJECT, + environment: DEFAULT_ENV, +}; + const getFeature = async (feature: string) => app.request.get(`/api/admin/features/${feature}`).expect(200); @@ -614,6 +647,24 @@ test('import features to existing project and environment', async () => { }); }); +test('import multiple features with same tag', async () => { + await createProjects(); + + await app.importToggles(importWithMultipleFeatures); + + const { body: tags1 } = await getTags(exportedFeature.name); + const { body: tags2 } = await getTags(anotherExportedFeature.name); + + expect(tags1).toMatchObject({ + version: 1, + tags: [{ value: 'tag1', type: 'simple' }], + }); + expect(tags2).toMatchObject({ + version: 1, + tags: [{ value: 'tag1', type: 'simple' }], + }); +}); + test('importing same JSON should work multiple times in a row', async () => { await createProjects(); await app.importToggles(defaultImportPayload);