diff --git a/app/selectors/featureFlagController/assetsUnifyState/index.test.ts b/app/selectors/featureFlagController/assetsUnifyState/index.test.ts index 0be0f30abed..f85209c1c69 100644 --- a/app/selectors/featureFlagController/assetsUnifyState/index.test.ts +++ b/app/selectors/featureFlagController/assetsUnifyState/index.test.ts @@ -1,6 +1,8 @@ import { selectIsAssetsUnifyStateEnabled, isAssetsUnifyStateFeatureEnabled, + getIsDeprecatedController, + selectIsControllerDeprecated, AssetsUnifyStateFeatureFlag, ASSETS_UNIFY_STATE_FLAG, ASSETS_UNIFY_STATE_FEATURE_VERSION_1, @@ -95,3 +97,109 @@ describe('selectIsAssetsUnifyStateEnabled', () => { expect(selectIsAssetsUnifyStateEnabled(mockedState)).toBe(false); }); }); + +describe('getIsDeprecatedController', () => { + it('returns true when the controller is listed in deprecatedControllers', () => { + const flag: AssetsUnifyStateFeatureFlag = { + enabled: true, + featureVersion: ASSETS_UNIFY_STATE_FEATURE_VERSION_1, + deprecatedControllers: ['AccountTrackerController'], + }; + + expect(getIsDeprecatedController(flag, 'AccountTrackerController')).toBe( + true, + ); + }); + + it('returns false when the controller is not listed in deprecatedControllers', () => { + const flag: AssetsUnifyStateFeatureFlag = { + enabled: true, + featureVersion: ASSETS_UNIFY_STATE_FEATURE_VERSION_1, + deprecatedControllers: ['SomeOtherController'], + }; + + expect(getIsDeprecatedController(flag, 'AccountTrackerController')).toBe( + false, + ); + }); + + it('returns false when deprecatedControllers is empty', () => { + const flag: AssetsUnifyStateFeatureFlag = { + enabled: true, + featureVersion: ASSETS_UNIFY_STATE_FEATURE_VERSION_1, + deprecatedControllers: [], + }; + + expect(getIsDeprecatedController(flag, 'AccountTrackerController')).toBe( + false, + ); + }); + + it('returns false when deprecatedControllers is absent', () => { + const flag: AssetsUnifyStateFeatureFlag = { + enabled: true, + featureVersion: ASSETS_UNIFY_STATE_FEATURE_VERSION_1, + }; + + expect(getIsDeprecatedController(flag, 'AccountTrackerController')).toBe( + false, + ); + }); + + it('returns false when flagValue is undefined', () => { + expect( + getIsDeprecatedController(undefined, 'AccountTrackerController'), + ).toBe(false); + }); + + it('returns false when flagValue is null', () => { + expect(getIsDeprecatedController(null, 'AccountTrackerController')).toBe( + false, + ); + }); +}); + +describe('selectIsControllerDeprecated', () => { + it('returns true when the controller is listed in deprecatedControllers', () => { + const mockedState = mockStateWith({ + enabled: true, + featureVersion: ASSETS_UNIFY_STATE_FEATURE_VERSION_1, + deprecatedControllers: ['AccountTrackerController'], + }); + + expect( + selectIsControllerDeprecated('AccountTrackerController')(mockedState), + ).toBe(true); + }); + + it('returns false when deprecatedControllers is empty', () => { + const mockedState = mockStateWith({ + enabled: true, + featureVersion: ASSETS_UNIFY_STATE_FEATURE_VERSION_1, + deprecatedControllers: [], + }); + + expect( + selectIsControllerDeprecated('AccountTrackerController')(mockedState), + ).toBe(false); + }); + + it('returns false when deprecatedControllers is absent', () => { + const mockedState = mockStateWith({ + enabled: true, + featureVersion: ASSETS_UNIFY_STATE_FEATURE_VERSION_1, + }); + + expect( + selectIsControllerDeprecated('AccountTrackerController')(mockedState), + ).toBe(false); + }); + + it('returns false when the flag is missing from state', () => { + expect( + selectIsControllerDeprecated('AccountTrackerController')( + mockedUndefinedFlagsState, + ), + ).toBe(false); + }); +}); diff --git a/app/selectors/featureFlagController/assetsUnifyState/index.ts b/app/selectors/featureFlagController/assetsUnifyState/index.ts index d84c6802d57..9be1715e89b 100644 --- a/app/selectors/featureFlagController/assetsUnifyState/index.ts +++ b/app/selectors/featureFlagController/assetsUnifyState/index.ts @@ -7,6 +7,7 @@ import { selectRemoteFeatureFlags } from '..'; export interface AssetsUnifyStateFeatureFlag { enabled: boolean; featureVersion: string | null; + deprecatedControllers?: string[]; } export const ASSETS_UNIFY_STATE_FLAG = 'assetsUnifyState'; @@ -35,6 +36,33 @@ export const isAssetsUnifyStateFeatureEnabled = ( ); }; +/** + * Checks if a controller is deprecated based on the assets unify state feature flag. + * + * @param flagValue - The raw feature flag value. + * @param controllerName - The name of the controller to check. + * @returns True if the controller is listed in deprecatedControllers, false otherwise. + */ +export const getIsDeprecatedController = ( + flagValue: unknown, + controllerName: string, +): boolean => { + if (!flagValue || typeof flagValue !== 'object') return false; + const parsed = flagValue as AssetsUnifyStateFeatureFlag; + return parsed.deprecatedControllers?.includes(controllerName) ?? false; +}; + +/** + * Selector factory to check if a specific controller is deprecated. + * + * @param controllerName - The name of the controller to check. + * @returns A selector that returns true if the controller is deprecated. + */ +export const selectIsControllerDeprecated = (controllerName: string) => + createSelector(selectRemoteFeatureFlags, (flags) => + getIsDeprecatedController(flags[ASSETS_UNIFY_STATE_FLAG], controllerName), + ); + /** * Selector to check if the assets unify state feature is enabled. * @returns Boolean indicating if the assets unify state feature is enabled. diff --git a/tests/feature-flags/feature-flag-registry.ts b/tests/feature-flags/feature-flag-registry.ts index 6641f83982b..ab78b53e638 100644 --- a/tests/feature-flags/feature-flag-registry.ts +++ b/tests/feature-flags/feature-flag-registry.ts @@ -250,6 +250,13 @@ export const FEATURE_FLAG_REGISTRY: Record = { enabled: false, featureVersion: null, minimumVersion: null, + deprecatedControllers: [], + }, + '8.3.0': { + enabled: true, + featureVersion: '1', + minimumVersion: '8.3.0', + deprecatedControllers: [], }, }, },