From 1419c8e926f0d82b111b086b8a9b1961ee92a929 Mon Sep 17 00:00:00 2001 From: Phani Raj Date: Fri, 22 Nov 2024 10:54:36 -0600 Subject: [PATCH] proces feature_flag_keys on Survey object --- src/__tests__/surveys.test.ts | 113 ++++++++++++++++++++++++++++++++++ src/posthog-surveys-types.ts | 6 ++ src/posthog-surveys.ts | 27 +++++++- 3 files changed, 143 insertions(+), 3 deletions(-) diff --git a/src/__tests__/surveys.test.ts b/src/__tests__/surveys.test.ts index defe94d2b..6a4fa6916 100644 --- a/src/__tests__/surveys.test.ts +++ b/src/__tests__/surveys.test.ts @@ -122,6 +122,44 @@ describe('surveys', () => { } as unknown as Survey, ] + const surveysWithFeatureFlagKeys: Survey[] = [ + { + name: 'survey with feature flags', + id: 'survey-with-flags', + description: 'survey with feature flags description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'what do you think?' }], + feature_flag_keys: [ + { key: 'flag1', value: 'linked-flag-key' }, + { key: 'flag2', value: 'survey-targeting-flag-key' }, + ], + start_date: new Date().toISOString(), + end_date: null, + } as unknown as Survey, + { + name: 'survey with disabled feature flags', + id: 'survey-with-disabled-flags', + description: 'survey with disabled feature flags description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'why not?' }], + feature_flag_keys: [ + { key: 'flag1', value: 'linked-flag-key2' }, + { key: 'flag2', value: 'survey-targeting-flag-key2' }, + ], + start_date: new Date().toISOString(), + end_date: null, + } as unknown as Survey, + { + name: 'survey without feature flags', + id: 'survey-without-flags', + description: 'survey without feature flags description', + type: SurveyType.Popover, + questions: [{ type: SurveyQuestionType.Open, question: 'any thoughts?' }], + start_date: new Date().toISOString(), + end_date: null, + } as unknown as Survey, + ] + beforeEach(() => { surveysResponse = { surveys: firstSurveys } @@ -652,6 +690,22 @@ describe('surveys', () => { expect(data).toEqual([activeSurvey, surveyWithSelector, surveyWithEverything]) }) }) + + it('returns only surveys with enabled feature flags', () => { + surveysResponse = { surveys: surveysWithFeatureFlagKeys } + + surveys.getActiveMatchingSurveys((data) => { + // Should include: + // - survey with enabled flags (survey-with-flags) + // - survey without flags (survey-without-flags) + // Should NOT include: + // - survey with disabled flags (survey-with-disabled-flags) + expect(data.length).toBe(2) + expect(data.map((s) => s.id)).toContain('survey-with-flags') + expect(data.map((s) => s.id)).toContain('survey-without-flags') + expect(data.map((s) => s.id)).not.toContain('survey-with-disabled-flags') + }) + }) }) describe('shuffling questions', () => { @@ -1172,4 +1226,63 @@ describe('surveys', () => { ) }) }) + + describe('checkFlags', () => { + it('should return true when no feature flags are specified', () => { + const survey = { id: '123', questions: [] } as Survey + const result = surveys.checkFlags(survey) + expect(result).toBe(true) + }) + + it('should return true when all feature flags are enabled', () => { + const survey = { + id: '123', + questions: [], + feature_flag_keys: [ + { key: 'flag1', value: 'flag-1' }, + { key: 'flag2', value: 'flag-2' }, + ], + } as Survey + + jest.spyOn(instance.featureFlags, 'isFeatureEnabled').mockImplementation(() => true) + + const result = surveys.checkFlags(survey) + expect(result).toBe(true) + }) + + it('should return false when any feature flag is disabled', () => { + const survey = { + id: '123', + questions: [], + feature_flag_keys: [ + { key: 'flag1', value: 'flag-1' }, + { key: 'flag2', value: 'flag-2' }, + ], + } as Survey + + jest.spyOn(instance.featureFlags, 'isFeatureEnabled').mockImplementation((flag) => + flag === 'flag-1' ? true : false + ) + + const result = surveys.checkFlags(survey) + expect(result).toBe(false) + }) + + it('should ignore feature flags with missing key or value', () => { + const survey = { + id: '123', + questions: [], + feature_flag_keys: [ + { key: '', value: 'flag-1' }, + { key: 'flag2', value: '' }, + { key: 'flag3', value: 'flag-3' }, + ], + } as Survey + + jest.spyOn(instance.featureFlags, 'isFeatureEnabled').mockImplementation(() => true) + + const result = surveys.checkFlags(survey) + expect(result).toBe(true) + }) + }) }) diff --git a/src/posthog-surveys-types.ts b/src/posthog-surveys-types.ts index 4c815732a..8313093b1 100644 --- a/src/posthog-surveys-types.ts +++ b/src/posthog-surveys-types.ts @@ -149,6 +149,12 @@ export interface Survey { name: string description: string type: SurveyType + feature_flag_keys: + | { + key: string + value?: string + }[] + | null linked_flag_key: string | null targeting_flag_key: string | null internal_targeting_flag_key: string | null diff --git a/src/posthog-surveys.ts b/src/posthog-surveys.ts index f7c90952b..4b25ef9bb 100644 --- a/src/posthog-surveys.ts +++ b/src/posthog-surveys.ts @@ -172,7 +172,12 @@ export class PostHogSurveys { // get all the surveys that have been activated so far with user actions. const activatedSurveys: string[] | undefined = this._surveyEventReceiver?.getSurveys() const targetingMatchedSurveys = conditionMatchedSurveys.filter((survey) => { - if (!survey.linked_flag_key && !survey.targeting_flag_key && !survey.internal_targeting_flag_key) { + if ( + !survey.linked_flag_key && + !survey.targeting_flag_key && + !survey.internal_targeting_flag_key && + !survey.feature_flag_keys?.length + ) { return true } const linkedFlagCheck = survey.linked_flag_key @@ -199,9 +204,13 @@ export class PostHogSurveys { survey.internal_targeting_flag_key && !overrideInternalTargetingFlagCheck ? this.instance.featureFlags.isFeatureEnabled(survey.internal_targeting_flag_key) : true - + const flagsCheck = this.checkFlags(survey) return ( - linkedFlagCheck && targetingFlagCheck && internalTargetingFlagCheck && eventBasedTargetingFlagCheck + linkedFlagCheck && + targetingFlagCheck && + internalTargetingFlagCheck && + eventBasedTargetingFlagCheck && + flagsCheck ) }) @@ -209,6 +218,18 @@ export class PostHogSurveys { }, forceReload) } + checkFlags(survey: Survey): boolean { + if (!survey.feature_flag_keys?.length) { + return true + } + + return survey.feature_flag_keys.every(({ key, value }) => { + if (!key || !value) { + return true + } + return this.instance.featureFlags.isFeatureEnabled(value) + }) + } getNextSurveyStep(survey: Survey, currentQuestionIndex: number, response: string | string[] | number | null) { const question = survey.questions[currentQuestionIndex] const nextQuestionIndex = currentQuestionIndex + 1