From bb40ffae3c2d8e5fdf0c0fb1255a633283892f6b Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Sat, 21 Feb 2026 13:38:06 -0800 Subject: [PATCH] feat: add survey registry for feature survey configurations (#8355) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Adds a centralized registry for feature survey configurations. ## Changes - Add `surveyRegistry.ts` with `FEATURE_SURVEYS` record for survey configs - Add helper functions `getSurveyConfig()` and `getEnabledSurveys()` - Export `FeatureId` type for type-safe feature references ## Part of Nightly Survey System This is part 3 of a stacked PR chain: 1. ✅ feat/feature-usage-tracker - useFeatureUsageTracker (merged in #8189) 2. ✅ feat/survey-eligibility - useSurveyEligibility (#8189, merged) 3. **feat/survey-config** - surveyRegistry.ts (this PR) 4. feat/survey-popover - NightlySurveyPopover.vue 5. feat/survey-integration - NightlySurveyController.vue ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8355-feat-add-survey-registry-for-feature-survey-configurations-2f66d73d365081faae6bda0c14c069d9) by [Unito](https://www.unito.io) --- src/platform/surveys/surveyRegistry.test.ts | 75 ++++++++++++++++++++ src/platform/surveys/surveyRegistry.ts | 19 +++++ src/platform/surveys/useSurveyEligibility.ts | 2 +- 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/platform/surveys/surveyRegistry.test.ts create mode 100644 src/platform/surveys/surveyRegistry.ts diff --git a/src/platform/surveys/surveyRegistry.test.ts b/src/platform/surveys/surveyRegistry.test.ts new file mode 100644 index 000000000..c79098536 --- /dev/null +++ b/src/platform/surveys/surveyRegistry.test.ts @@ -0,0 +1,75 @@ +import { afterEach, beforeEach, describe, expect, it } from 'vitest' + +import type { FeatureSurveyConfig } from './useSurveyEligibility' + +import { + FEATURE_SURVEYS, + getEnabledSurveys, + getSurveyConfig +} from './surveyRegistry' + +const TEST_FEATURE_ID = '__test-feature__' +const TEST_CONFIG: FeatureSurveyConfig = { + featureId: TEST_FEATURE_ID, + typeformId: 'test-form-123', + triggerThreshold: 5, + delayMs: 3000, + enabled: true +} + +describe('surveyRegistry', () => { + let originalEntries: Record + + beforeEach(() => { + originalEntries = { ...FEATURE_SURVEYS } + FEATURE_SURVEYS[TEST_FEATURE_ID] = TEST_CONFIG + }) + + afterEach(() => { + for (const key of Object.keys(FEATURE_SURVEYS)) { + delete FEATURE_SURVEYS[key] + } + Object.assign(FEATURE_SURVEYS, originalEntries) + }) + + describe('getSurveyConfig', () => { + it('returns undefined for unknown feature', () => { + expect(getSurveyConfig('nonexistent-feature')).toBeUndefined() + }) + + it('returns config for registered feature', () => { + const config = getSurveyConfig(TEST_FEATURE_ID) + expect(config).toEqual(TEST_CONFIG) + }) + }) + + describe('getEnabledSurveys', () => { + it('includes surveys with enabled: true', () => { + const enabled = getEnabledSurveys() + expect(enabled).toContainEqual(TEST_CONFIG) + }) + + it('includes surveys where enabled is undefined', () => { + const implicitlyEnabled: FeatureSurveyConfig = { + featureId: '__implicit__', + typeformId: 'form-456' + } + FEATURE_SURVEYS['__implicit__'] = implicitlyEnabled + + const enabled = getEnabledSurveys() + expect(enabled).toContainEqual(implicitlyEnabled) + }) + + it('excludes surveys with enabled: false', () => { + const disabledConfig: FeatureSurveyConfig = { + featureId: '__disabled__', + typeformId: 'form-789', + enabled: false + } + FEATURE_SURVEYS['__disabled__'] = disabledConfig + + const enabled = getEnabledSurveys() + expect(enabled).not.toContainEqual(disabledConfig) + }) + }) +}) diff --git a/src/platform/surveys/surveyRegistry.ts b/src/platform/surveys/surveyRegistry.ts new file mode 100644 index 000000000..e93f58181 --- /dev/null +++ b/src/platform/surveys/surveyRegistry.ts @@ -0,0 +1,19 @@ +import type { FeatureSurveyConfig } from './useSurveyEligibility' + +/** + * Registry of all feature surveys. + * Add new surveys here when targeting specific features for feedback. + */ +export const FEATURE_SURVEYS: Record = {} + +export function getSurveyConfig( + featureId: string +): FeatureSurveyConfig | undefined { + return FEATURE_SURVEYS[featureId] +} + +export function getEnabledSurveys(): FeatureSurveyConfig[] { + return Object.values(FEATURE_SURVEYS).filter( + (config) => config.enabled !== false + ) +} diff --git a/src/platform/surveys/useSurveyEligibility.ts b/src/platform/surveys/useSurveyEligibility.ts index 37929e25c..e8e86f230 100644 --- a/src/platform/surveys/useSurveyEligibility.ts +++ b/src/platform/surveys/useSurveyEligibility.ts @@ -6,7 +6,7 @@ import { isCloud, isDesktop, isNightly } from '@/platform/distribution/types' import { useFeatureUsageTracker } from './useFeatureUsageTracker' -interface FeatureSurveyConfig { +export interface FeatureSurveyConfig { /** Feature identifier. Must remain static after initialization. */ featureId: string typeformId: string