Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 1 addition & 115 deletions app/contexts/FeatureFlagOverrideContext.test.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import React from 'react';
import {
renderHook,
act,
render,
screen,
waitFor,
} from '@testing-library/react-native';
import { renderHook, act, render, screen } from '@testing-library/react-native';
import { useSelector } from 'react-redux';
import { Text } from 'react-native';
import {
Expand Down Expand Up @@ -54,15 +48,6 @@ jest.mock('../util/feature-flags', () => ({
getFeatureFlagType: jest.fn(),
}));

// Mock useMetrics hook
const mockAddTraitsToUser = jest.fn();
jest.mock('../components/hooks/useMetrics/useMetrics', () => ({
__esModule: true,
default: jest.fn(() => ({
addTraitsToUser: mockAddTraitsToUser,
})),
}));

describe('FeatureFlagOverrideContext', () => {
let mockUseSelector: jest.MockedFunction<typeof useSelector>;
let mockGetFeatureFlagType: jest.MockedFunction<typeof getFeatureFlagType>;
Expand All @@ -72,7 +57,6 @@ describe('FeatureFlagOverrideContext', () => {

beforeEach(() => {
jest.clearAllMocks();
mockAddTraitsToUser.mockClear();
mockSetFlagOverride.mockClear();
mockRemoveFlagOverride.mockClear();
mockClearAllFlagOverrides.mockClear();
Expand Down Expand Up @@ -729,102 +713,4 @@ describe('FeatureFlagOverrideContext', () => {
expect(result.current.hasOverride('')).toBe(true);
});
});

describe('Remote Feature Flag Change Tracking', () => {
it('adds all feature flags to user traits in bulk when received', async () => {
const mockFlags = {
booleanFlag: true,
stringFlag: 'variant_a',
numberFlag: 42,
};
mockUseSelector.mockReturnValue(mockFlags);

renderHook(() => useFeatureFlagOverride(), {
wrapper: createWrapper,
});

await waitFor(() => {
expect(mockAddTraitsToUser).toHaveBeenCalledWith({
booleanFlag: true,
stringFlag: 'variant_a',
numberFlag: 42,
});
});
});

it('adds all feature flags to user traits in bulk when flags change', async () => {
const initialFlags = { flag1: true, flag2: 'variant_a' };
mockUseSelector.mockReturnValue(initialFlags);

const { rerender } = renderHook(() => useFeatureFlagOverride(), {
wrapper: createWrapper,
});

mockAddTraitsToUser.mockClear();

const updatedFlags = { flag1: false, flag2: 'variant_b', newFlag: 100 };
mockUseSelector.mockReturnValue(updatedFlags);

rerender(null);

await waitFor(() => {
expect(mockAddTraitsToUser).toHaveBeenCalledWith({
flag1: false,
flag2: 'variant_b',
newFlag: 100,
});
});
});

it('does not call addTraitsToUser when no feature flags exist', async () => {
mockUseSelector.mockReturnValue({});

renderHook(() => useFeatureFlagOverride(), {
wrapper: createWrapper,
});

await waitFor(
() => {
expect(mockAddTraitsToUser).not.toHaveBeenCalled();
},
{ timeout: 200 },
);
});

it('sends user traits in a single bulk call, not per-flag', async () => {
const mockFlags = { flag1: true, flag2: 'variant', flag3: 123 };
mockUseSelector.mockReturnValue(mockFlags);

renderHook(() => useFeatureFlagOverride(), {
wrapper: createWrapper,
});

await waitFor(() => {
// Should be called exactly once with all flags
expect(mockAddTraitsToUser).toHaveBeenCalledTimes(1);
expect(mockAddTraitsToUser).toHaveBeenCalledWith({
flag1: true,
flag2: 'variant',
flag3: 123,
});
});
});
});

describe('Bulk Traits on Mount', () => {
it('calls addTraitsToUser in bulk on mount with all feature flags', () => {
const mockFlags = { stringFlag: 'test', boolFlag: true };
mockUseSelector.mockReturnValue(mockFlags);

renderHook(() => useFeatureFlagOverride(), {
wrapper: createWrapper,
});

// useEffect sends all flags in bulk on mount
expect(mockAddTraitsToUser).toHaveBeenCalledWith({
stringFlag: 'test',
boolFlag: true,
});
});
});
});
10 changes: 0 additions & 10 deletions app/contexts/FeatureFlagOverrideContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import React, {
useCallback,
ReactNode,
useMemo,
useEffect,
} from 'react';
import { useSelector } from 'react-redux';
import {
Expand All @@ -13,7 +12,6 @@ import {
selectRawFeatureFlags,
} from '../selectors/featureFlagController';
import { FeatureFlagInfo, getFeatureFlagType } from '../util/feature-flags';
import useMetrics from '../components/hooks/useMetrics/useMetrics';
import Engine from '../core/Engine';
import type { Json } from '@metamask/utils';

Expand Down Expand Up @@ -44,21 +42,13 @@ interface FeatureFlagOverrideProviderProps {
export const FeatureFlagOverrideProvider: React.FC<
FeatureFlagOverrideProviderProps
> = ({ children }) => {
const { addTraitsToUser } = useMetrics();
// Get the initial feature flags from Redux
const featureFlagsWithOverrides = useSelector(selectRemoteFeatureFlags);
const rawFeatureFlags = useSelector(selectRawFeatureFlags);

// Get overrides from controller state via Redux
const overrides = useSelector(selectLocalOverrides);

// Track remote feature flags and add all flags to user traits in bulk
useEffect(() => {
if (rawFeatureFlags && Object.keys(rawFeatureFlags).length > 0) {
addTraitsToUser(rawFeatureFlags);
}
}, [rawFeatureFlags, addTraitsToUser]);

const setOverride = useCallback((key: string, value: unknown) => {
Engine.context?.RemoteFeatureFlagController?.setFlagOverride(
key,
Expand Down
Loading
Loading