Skip to content

Commit d0f7bef

Browse files
refactor(analytics): migrate Batch 2-6: mobile-core-ux (MetaMask#26182)
## **Description** Phase 2 analytics migration (Batch 2-6): migrate mobile-core-ux's Network Management components and hooks from the legacy MetaMetrics system to the new analytics system. **Reason**: Deprecate MetaMetrics in favour of the shared analytics utility and AnalyticsController. **Changes**: - `NetworkSelector.tsx` now uses `analytics.identify()` from `app/util/analytics/analytics` instead of `MetaMetrics.getInstance().addTraitsToUser()`. - `useSwitchNetworks.ts`, `useNetworkConnectionBanner.ts`, and `useAddPopularNetwork.ts` now use `useAnalytics` from `app/components/hooks/useAnalytics/useAnalytics` instead of `useMetrics`; `MetaMetricsEvents` is imported from `app/core/Analytics`. - Test mocks updated to mock `useAnalytics` and `analytics` instead of `useMetrics` and `MetaMetrics`. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-298 (Batch 2-6) ## **Manual testing steps** ```gherkin Feature: Network Management analytics Scenario: user triggers a network management flow event Given app is open and user is in a network management flow When user performs an action that triggers analytics (e.g. network switch, add popular network, network connection banner interaction) Then the event is tracked on Mixpanel ``` ## **Screenshots/Recordings** N/A – analytics migration, no UI change. ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Primarily a refactor of analytics wiring and test mocks with minimal impact to user-facing behavior; main risk is altered analytics/identify calls or event payloads. > > **Overview** > Migrates Network Management analytics instrumentation off legacy MetaMetrics APIs. > > `NetworkSelector` now records network-removal traits via `analytics.identify(removeItemFromChainIdList(...))` instead of `MetaMetrics.getInstance().addTraitsToUser(...)`, and `useSwitchNetworks`, `useAddPopularNetwork`, and `useNetworkConnectionBanner` now use `useAnalytics` (with `MetaMetricsEvents` imported from `core/Analytics`) in place of `useMetrics`. Associated unit tests were updated to mock `useAnalytics`/`analytics` and to align with renamed IDs (`getAnalyticsId` vs `getMetaMetricsId`) and event builder shape. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 593461a. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent a261eb3 commit d0f7bef

8 files changed

Lines changed: 36 additions & 32 deletions

File tree

app/components/Views/NetworkSelector/NetworkSelector.test.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,25 @@ jest.mock('../../../util/metrics/MultichainAPI/networkMetricUtils', () => ({
2121
}),
2222
}));
2323

24-
jest.mock('../../../components/hooks/useMetrics', () => ({
25-
useMetrics: () => ({
24+
jest.mock('../../../components/hooks/useAnalytics/useAnalytics', () => ({
25+
useAnalytics: () => ({
2626
trackEvent: jest.fn(),
2727
createEventBuilder: jest.fn(() => ({
2828
addProperties: jest.fn(() => ({
2929
build: jest.fn(),
3030
})),
31+
build: jest.fn(),
3132
})),
3233
}),
3334
}));
3435

35-
jest.mock('../../../core/Analytics', () => ({
36-
MetaMetrics: {
37-
getInstance: jest.fn().mockReturnValue({
38-
addTraitsToUser: jest.fn(),
39-
}),
36+
jest.mock('../../../util/analytics/analytics', () => ({
37+
analytics: {
38+
identify: jest.fn(),
4039
},
40+
}));
41+
42+
jest.mock('../../../core/Analytics', () => ({
4143
MetaMetricsEvents: {
4244
NETWORK_SWITCHED: 'Network Switched',
4345
},

app/components/Views/NetworkSelector/NetworkSelector.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ import { isNonEvmChainId } from '../../../core/Multichain/utils';
102102
import { MultichainNetworkConfiguration } from '@metamask/multichain-network-controller';
103103
import { useSwitchNetworks } from './useSwitchNetworks';
104104
import { removeItemFromChainIdList } from '../../../util/metrics/MultichainAPI/networkMetricUtils';
105-
import { MetaMetrics } from '../../../core/Analytics';
105+
import { analytics } from '../../../util/analytics/analytics';
106106
import {
107107
NETWORK_SELECTOR_SOURCES,
108108
NetworkSelectorSource,
@@ -884,9 +884,7 @@ const NetworkSelector = () => {
884884
const { NetworkController } = Engine.context;
885885
NetworkController.removeNetwork(chainId);
886886

887-
MetaMetrics.getInstance().addTraitsToUser(
888-
removeItemFromChainIdList(chainId),
889-
);
887+
analytics.identify(removeItemFromChainIdList(chainId));
890888

891889
// set tokenNetworkFilter
892890
const { PreferencesController } = Engine.context;

app/components/Views/NetworkSelector/useNetworkSwitch.test.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
NetworkType,
44
} from '../../hooks/useNetworksByNamespace/useNetworksByNamespace';
55
import { useNetworkSelection } from '../../hooks/useNetworkSelection/useNetworkSelection';
6-
import { useMetrics } from '../../hooks/useMetrics';
6+
import { useAnalytics } from '../../hooks/useAnalytics/useAnalytics';
77
import Engine from '../../../core/Engine';
88

99
// Mock the feature flags
@@ -23,8 +23,8 @@ jest.mock('../../hooks/useNetworkSelection/useNetworkSelection', () => ({
2323
useNetworkSelection: jest.fn(),
2424
}));
2525

26-
jest.mock('../../hooks/useMetrics', () => ({
27-
useMetrics: jest.fn(),
26+
jest.mock('../../hooks/useAnalytics/useAnalytics', () => ({
27+
useAnalytics: jest.fn(),
2828
}));
2929

3030
// Mock Engine
@@ -80,7 +80,9 @@ const mockUseNetworksByNamespace =
8080
const mockUseNetworkSelection = useNetworkSelection as jest.MockedFunction<
8181
typeof useNetworkSelection
8282
>;
83-
const mockUseMetrics = useMetrics as jest.MockedFunction<typeof useMetrics>;
83+
const mockUseAnalytics = useAnalytics as jest.MockedFunction<
84+
typeof useAnalytics
85+
>;
8486

8587
const mockSelectNetwork = jest.fn();
8688
const mockTrackEvent = jest.fn();
@@ -108,7 +110,7 @@ describe('useSwitchNetworks Feature Flag Tests', () => {
108110
customNetworksToReset: [],
109111
});
110112

111-
mockUseMetrics.mockReturnValue({
113+
mockUseAnalytics.mockReturnValue({
112114
trackEvent: mockTrackEvent,
113115
createEventBuilder: mockCreateEventBuilder,
114116
isEnabled: () => true,
@@ -119,7 +121,7 @@ describe('useSwitchNetworks Feature Flag Tests', () => {
119121
getDeleteRegulationCreationDate: jest.fn(),
120122
getDeleteRegulationId: jest.fn(),
121123
isDataRecorded: jest.fn(),
122-
getMetaMetricsId: jest.fn(),
124+
getAnalyticsId: jest.fn(),
123125
});
124126

125127
// Mock the event builder
@@ -164,7 +166,7 @@ describe('useSwitchNetworks Feature Flag Tests', () => {
164166
// Verify that the hooks are properly initialized
165167
expect(mockUseNetworksByNamespace).toBeDefined();
166168
expect(mockUseNetworkSelection).toBeDefined();
167-
expect(mockUseMetrics).toBeDefined();
169+
expect(mockUseAnalytics).toBeDefined();
168170
});
169171

170172
it('should have all necessary Engine controllers available', () => {
@@ -183,7 +185,7 @@ describe('useSwitchNetworks Feature Flag Tests', () => {
183185

184186
it('should have proper metrics setup', () => {
185187
// Verify that metrics are properly set up
186-
expect(mockUseMetrics).toBeDefined();
188+
expect(mockUseAnalytics).toBeDefined();
187189
expect(mockTrackEvent).toBeDefined();
188190
expect(mockCreateEventBuilder).toBeDefined();
189191
});

app/components/Views/NetworkSelector/useSwitchNetworks.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
selectEvmNetworkConfigurationsByChainId,
2020
selectIsAllNetworks,
2121
} from '../../../selectors/networkController';
22-
import { useMetrics } from '../../hooks/useMetrics';
22+
import { useAnalytics } from '../../hooks/useAnalytics/useAnalytics';
2323
import { MetaMetricsEvents } from '../../../core/Analytics';
2424
import {
2525
TraceContext,
@@ -67,7 +67,7 @@ export function useSwitchNetworks({
6767
const networkConfigurations = useSelector(
6868
selectEvmNetworkConfigurationsByChainId,
6969
);
70-
const { trackEvent, createEventBuilder } = useMetrics();
70+
const { trackEvent, createEventBuilder } = useAnalytics();
7171

7272
/**
7373
* Sets the token network filter based on the chain ID

app/components/hooks/useAddPopularNetwork/useAddPopularNetwork.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { renderHook, act } from '@testing-library/react-hooks';
22
import { useAddPopularNetwork } from './useAddPopularNetwork';
33
import Engine from '../../../core/Engine';
44
import { useDispatch, useSelector } from 'react-redux';
5-
import { useMetrics } from '../useMetrics';
5+
import { useAnalytics } from '../useAnalytics/useAnalytics';
66
import { useNetworkEnablement } from '../useNetworkEnablement/useNetworkEnablement';
77
import { networkSwitched } from '../../../actions/onboardNetwork';
88
import { MetaMetricsEvents } from '../../../core/Analytics';
@@ -14,8 +14,8 @@ jest.mock('react-redux', () => ({
1414
useSelector: jest.fn(),
1515
}));
1616

17-
jest.mock('../useMetrics', () => ({
18-
useMetrics: jest.fn(),
17+
jest.mock('../useAnalytics/useAnalytics', () => ({
18+
useAnalytics: jest.fn(),
1919
}));
2020

2121
jest.mock('../useNetworkEnablement/useNetworkEnablement', () => ({
@@ -65,7 +65,7 @@ describe('useAddPopularNetwork', () => {
6565

6666
(useDispatch as jest.Mock).mockReturnValue(mockDispatch);
6767
(useSelector as jest.Mock).mockReturnValue({});
68-
(useMetrics as jest.Mock).mockReturnValue({
68+
(useAnalytics as jest.Mock).mockReturnValue({
6969
trackEvent: mockTrackEvent,
7070
createEventBuilder: mockCreateEventBuilder.mockReturnValue({
7171
addProperties: jest.fn().mockReturnValue({

app/components/hooks/useAddPopularNetwork/useAddPopularNetwork.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { toHex } from '@metamask/controller-utils';
77
import Engine from '../../../core/Engine';
88
import { networkSwitched } from '../../../actions/onboardNetwork';
99
import { MetaMetricsEvents } from '../../../core/Analytics';
10-
import { useMetrics } from '../useMetrics';
10+
import { useAnalytics } from '../useAnalytics/useAnalytics';
1111
import { selectEvmNetworkConfigurationsByChainId } from '../../../selectors/networkController';
1212
import { addItemToChainIdList } from '../../../util/metrics/MultichainAPI/networkMetricUtils';
1313
import { Network } from '../../Views/Settings/NetworksSettings/NetworkSettings/CustomNetworkView/CustomNetwork.types';
@@ -36,7 +36,7 @@ interface UseAddPopularNetworkResult {
3636
*/
3737
export const useAddPopularNetwork = (): UseAddPopularNetworkResult => {
3838
const dispatch = useDispatch();
39-
const { trackEvent, createEventBuilder, addTraitsToUser } = useMetrics();
39+
const { trackEvent, createEventBuilder, addTraitsToUser } = useAnalytics();
4040
const networkConfigurationByChainId = useSelector(
4141
selectEvmNetworkConfigurationsByChainId,
4242
);

app/components/hooks/useNetworkConnectionBanner/useNetworkConnectionBanner.test.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import {
1212

1313
import useNetworkConnectionBanner from './useNetworkConnectionBanner';
1414
import Engine from '../../../core/Engine';
15-
import { MetaMetricsEvents, useMetrics } from '../useMetrics';
15+
import { useAnalytics } from '../useAnalytics/useAnalytics';
16+
import { MetaMetricsEvents } from '../../../core/Analytics';
1617
import { selectNetworkConnectionBannerState } from '../../../selectors/networkConnectionBanner';
1718
import { selectIsDeviceOffline } from '../../../selectors/connectivityController';
1819
import { selectEVMEnabledNetworks } from '../../../selectors/networkEnablementController';
@@ -28,7 +29,7 @@ import { IconName } from '../../../component-library/components/Icons/Icon';
2829
jest.mock('@react-navigation/native');
2930
jest.mock('../../../core/Engine');
3031
jest.mock('../../../selectors/networkEnablementController');
31-
jest.mock('../useMetrics');
32+
jest.mock('../useAnalytics/useAnalytics');
3233
jest.mock('../../../selectors/networkConnectionBanner');
3334
jest.mock('../../../selectors/connectivityController');
3435
jest.mock('react-redux', () => {
@@ -207,7 +208,7 @@ describe('useNetworkConnectionBanner', () => {
207208
build: mockBuild,
208209
}));
209210

210-
(useMetrics as jest.Mock).mockReturnValue({
211+
(useAnalytics as jest.Mock).mockReturnValue({
211212
trackEvent: stableTrackEvent,
212213
createEventBuilder: stableCreateEventBuilder,
213214
});

app/components/hooks/useNetworkConnectionBanner/useNetworkConnectionBanner.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { selectNetworkConnectionBannerState } from '../../../selectors/networkCo
77
import { selectIsDeviceOffline } from '../../../selectors/connectivityController';
88
import Engine from '../../../core/Engine';
99
import Routes from '../../../constants/navigation/Routes';
10-
import { MetaMetricsEvents, useMetrics } from '../useMetrics';
10+
import { useAnalytics } from '../useAnalytics/useAnalytics';
11+
import { MetaMetricsEvents } from '../../../core/Analytics';
1112
import {
1213
hideNetworkConnectionBanner,
1314
showNetworkConnectionBanner,
@@ -55,7 +56,7 @@ const useNetworkConnectionBanner = (): {
5556
} => {
5657
const dispatch = useDispatch();
5758
const navigation = useNavigation();
58-
const { trackEvent, createEventBuilder } = useMetrics();
59+
const { trackEvent, createEventBuilder } = useAnalytics();
5960
const { toastRef } = useContext(ToastContext);
6061
const networkConnectionBannerState = useSelector(
6162
selectNetworkConnectionBannerState,

0 commit comments

Comments
 (0)