mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-03 04:10:43 +00:00
feat(ui): add summary page feature flag to local storage and make it generic (#14807)
Co-authored-by: Chris Collins <chriscollins3456@gmail.com>
This commit is contained in:
parent
7768abc6eb
commit
d268d14ee2
@ -64,11 +64,4 @@ describe('useShowAssetSummaryPage', () => {
|
|||||||
const { result } = renderHook(() => useShowAssetSummaryPage());
|
const { result } = renderHook(() => useShowAssetSummaryPage());
|
||||||
expect(result.current).toBe(false);
|
expect(result.current).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false when appConfig is undefined', () => {
|
|
||||||
mockedUseAppConfig.mockReturnValue(undefined as any);
|
|
||||||
|
|
||||||
const { result } = renderHook(() => useShowAssetSummaryPage());
|
|
||||||
expect(result.current).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
import { useAppConfig } from '@app/useAppConfig';
|
import { useFeatureFlag } from '@app/sharedV2/hooks/useFeatureFlag';
|
||||||
|
|
||||||
export function useShowAssetSummaryPage() {
|
export function useShowAssetSummaryPage() {
|
||||||
const appConfig = useAppConfig();
|
const assetSummaryPageV1 = useFeatureFlag('assetSummaryPageV1');
|
||||||
if (appConfig?.loaded) {
|
return assetSummaryPageV1;
|
||||||
return appConfig.config.featureFlags.assetSummaryPageV1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,122 @@
|
|||||||
|
import { renderHook } from '@testing-library/react-hooks';
|
||||||
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
|
import { loadFeatureFlagFromLocalStorage, useFeatureFlag } from '@app/sharedV2/hooks/useFeatureFlag';
|
||||||
|
import { useAppConfig } from '@app/useAppConfig';
|
||||||
|
|
||||||
|
// Mocks
|
||||||
|
const localStorageMock = (() => {
|
||||||
|
let store: Record<string, string> = {};
|
||||||
|
return {
|
||||||
|
getItem: (key: string) => store[key] ?? null,
|
||||||
|
setItem: (key: string, value: string) => {
|
||||||
|
store[key] = value;
|
||||||
|
},
|
||||||
|
clear: () => {
|
||||||
|
store = {};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
Object.defineProperty(window, 'localStorage', { value: localStorageMock });
|
||||||
|
|
||||||
|
vi.mock('@app/useAppConfig', () => ({
|
||||||
|
useAppConfig: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('useFeatureFlag', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
localStorage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return flag value from appConfig and set localStorage when config loaded', () => {
|
||||||
|
(useAppConfig as any).mockReturnValue({
|
||||||
|
loaded: true,
|
||||||
|
config: { featureFlags: { myFlag: true } },
|
||||||
|
});
|
||||||
|
|
||||||
|
const { result } = renderHook(() => useFeatureFlag('myFlag'));
|
||||||
|
|
||||||
|
expect(result.current).toBe(true);
|
||||||
|
expect(localStorage.getItem('myFlag')).toBe('true');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not set localStorage if value is unchanged', () => {
|
||||||
|
localStorage.setItem('myFlag', 'true');
|
||||||
|
|
||||||
|
(useAppConfig as any).mockReturnValue({
|
||||||
|
loaded: true,
|
||||||
|
config: { featureFlags: { myFlag: true } },
|
||||||
|
});
|
||||||
|
|
||||||
|
const setItemSpy = vi.spyOn(localStorage, 'setItem');
|
||||||
|
|
||||||
|
renderHook(() => useFeatureFlag('myFlag'));
|
||||||
|
|
||||||
|
expect(setItemSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return value from localStorage if config not loaded', () => {
|
||||||
|
localStorage.setItem('myFlag', 'true');
|
||||||
|
|
||||||
|
(useAppConfig as any).mockReturnValue({
|
||||||
|
loaded: false,
|
||||||
|
config: { featureFlags: { myFlag: false } },
|
||||||
|
});
|
||||||
|
|
||||||
|
const { result } = renderHook(() => useFeatureFlag('myFlag'));
|
||||||
|
|
||||||
|
expect(result.current).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if localStorage has no value and config not loaded', () => {
|
||||||
|
(useAppConfig as any).mockReturnValue({
|
||||||
|
loaded: false,
|
||||||
|
config: { featureFlags: {} },
|
||||||
|
});
|
||||||
|
|
||||||
|
const { result } = renderHook(() => useFeatureFlag('myFlag'));
|
||||||
|
|
||||||
|
expect(result.current).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if feature flag is undefined in loaded config', () => {
|
||||||
|
(useAppConfig as any).mockReturnValue({
|
||||||
|
loaded: true,
|
||||||
|
config: { featureFlags: {} },
|
||||||
|
});
|
||||||
|
|
||||||
|
const { result } = renderHook(() => useFeatureFlag('myFlag'));
|
||||||
|
expect(result.current).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should store false value in localStorage if feature flag is false and config loaded', () => {
|
||||||
|
(useAppConfig as any).mockReturnValue({
|
||||||
|
loaded: true,
|
||||||
|
config: { featureFlags: { myFlag: false } },
|
||||||
|
});
|
||||||
|
|
||||||
|
renderHook(() => useFeatureFlag('myFlag'));
|
||||||
|
expect(localStorage.getItem('myFlag')).toBe('false');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('loadFeatureFlagFromLocalStorage', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
localStorage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true if localStorage value is true', () => {
|
||||||
|
localStorage.setItem('someFlag', 'true');
|
||||||
|
expect(loadFeatureFlagFromLocalStorage('someFlag')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if localStorage value is false', () => {
|
||||||
|
localStorage.setItem('someFlag', 'false');
|
||||||
|
expect(loadFeatureFlagFromLocalStorage('someFlag')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if localStorage has no key', () => {
|
||||||
|
expect(loadFeatureFlagFromLocalStorage('someFlag')).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
31
datahub-web-react/src/app/sharedV2/hooks/useFeatureFlag.ts
Normal file
31
datahub-web-react/src/app/sharedV2/hooks/useFeatureFlag.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { useAppConfig } from '@app/useAppConfig';
|
||||||
|
|
||||||
|
export function useFeatureFlag(featureFlagKey: string) {
|
||||||
|
const appConfig = useAppConfig();
|
||||||
|
|
||||||
|
const featureFlagValue = appConfig?.config?.featureFlags?.[featureFlagKey];
|
||||||
|
|
||||||
|
if (appConfig.loaded) {
|
||||||
|
setFeatureFlagInLocalStorage(featureFlagKey, featureFlagValue);
|
||||||
|
return featureFlagValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return loadFeatureFlagFromLocalStorage(featureFlagKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFeatureFlagInLocalStorage(flagKey: string, value: boolean) {
|
||||||
|
const rawValue = localStorage.getItem(flagKey);
|
||||||
|
const storedValue = rawValue === null ? undefined : rawValue === 'true';
|
||||||
|
|
||||||
|
if (rawValue === null || storedValue !== value) {
|
||||||
|
saveFeatureFlagToLocalStorage(flagKey, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function loadFeatureFlagFromLocalStorage(flagKey: string): boolean {
|
||||||
|
return localStorage.getItem(flagKey) === 'true';
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveFeatureFlagToLocalStorage(flagKey: string, value: boolean) {
|
||||||
|
localStorage.setItem(flagKey, String(value));
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user