Skip to content

Commit a14a1f2

Browse files
refactor(analytics): migrate Batch 3-7: mobile-platform (#26385)
## **Description** Phase 3 analytics migration (Batch 3-7): migrate Payment Request's `PaymentRequest` class component from `withMetricsAwareness` HOC to the new analytics system. **Reason**: Deprecate MetaMetrics in favour of the shared analytics utility and AnalyticsController. **Changes**: `PaymentRequest/index.js` now uses `analytics.trackEvent()` and `AnalyticsEventBuilder` from `app/util/analytics` directly instead of the `withMetricsAwareness` HOC; test mocks updated to mock the analytics utility instead of MetaMetrics. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: https://consensyssoftware.atlassian.net/browse/MCWP-301 (Batch 3-7) ## **Manual testing steps** ```gherkin Feature: Payment Request analytics Scenario: user triggers a payment request flow event Given app is open and user is in a payment request flow When user performs an action that triggers analytics (e.g. network selector press) 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** > Analytics plumbing is swapped from `withMetricsAwareness` to the shared `analytics` utility with minimal behavioral change and no sensitive data handling. > > **Overview** > Migrates `PaymentRequest` analytics from the deprecated `withMetricsAwareness`/MetaMetrics injection to the shared `analytics.trackEvent()` + `AnalyticsEventBuilder` flow when the network picker is pressed, preserving the `chain_id` property. > > Removes the `metrics` prop/HOC wrapper and updates tests to mock the new analytics module (plus a small TypeScript cast workaround for the connected `.js` component). > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 89e949b. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent 14c57d5 commit a14a1f2

2 files changed

Lines changed: 22 additions & 20 deletions

File tree

app/components/UI/PaymentRequest/index.js

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,10 @@ import { selectContractExchangeRates } from '../../../selectors/tokenRatesContro
6464
import { selectSelectedInternalAccountFormattedAddress } from '../../../selectors/accountsController';
6565
import PickerNetwork from '../../../component-library/components/Pickers/PickerNetwork/PickerNetwork';
6666
import Routes from '../../../constants/navigation/Routes';
67-
import { withMetricsAwareness } from '../../../components/hooks/useMetrics';
6867
import { RequestPaymentViewSelectors } from '../ReceiveRequest/RequestPaymentView.testIds';
6968
import { MetaMetricsEvents } from '../../../core/Analytics';
69+
import { analytics } from '../../../util/analytics/analytics';
70+
import { AnalyticsEventBuilder } from '../../../util/analytics/AnalyticsEventBuilder';
7071

7172
const KEYBOARD_OFFSET = 120;
7273
const createStyles = (colors) =>
@@ -308,10 +309,6 @@ class PaymentRequest extends PureComponent {
308309
* Object that represents the current route info like params passed to it
309310
*/
310311
route: PropTypes.object,
311-
/**
312-
* Metrics injected by withMetricsAwareness HOC
313-
*/
314-
metrics: PropTypes.object,
315312
/**
316313
* Network configurations
317314
*/
@@ -910,9 +907,10 @@ class PaymentRequest extends PureComponent {
910907
this.props.navigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, {
911908
screen: Routes.SHEET.NETWORK_SELECTOR,
912909
});
913-
this.props.metrics.trackEvent(
914-
this.props.metrics
915-
.createEventBuilder(MetaMetricsEvents.NETWORK_SELECTOR_PRESSED)
910+
analytics.trackEvent(
911+
AnalyticsEventBuilder.createEventBuilder(
912+
MetaMetricsEvents.NETWORK_SELECTOR_PRESSED,
913+
)
916914
.addProperties({
917915
chain_id: getDecimalChainId(this.props.chainId),
918916
})
@@ -967,4 +965,4 @@ const mapStateToProps = (state) => ({
967965
networkImageSource: selectNetworkImageSource(state),
968966
});
969967

970-
export default withMetricsAwareness(connect(mapStateToProps)(PaymentRequest));
968+
export default connect(mapStateToProps)(PaymentRequest);

app/components/UI/PaymentRequest/index.test.tsx

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ import {
66
userEvent,
77
waitFor,
88
} from '@testing-library/react-native';
9-
import PaymentRequest from './index';
9+
import PaymentRequestConnected from './index';
10+
11+
// Workaround: source is a .js file so TypeScript can't infer PropTypes;
12+
// connect() produces a narrow type that rejects valid ownProps like chainId.
13+
const PaymentRequest = PaymentRequestConnected as React.ComponentType<
14+
Record<string, unknown>
15+
>;
1016
import { Provider } from 'react-redux';
1117
import configureMockStore from 'redux-mock-store';
1218
import { SolScope } from '@metamask/keyring-api';
@@ -21,6 +27,13 @@ jest.mock('react', () => ({
2127
useState: jest.fn(),
2228
}));
2329

30+
const mockTrackEvent = jest.fn();
31+
jest.mock('../../../util/analytics/analytics', () => ({
32+
analytics: {
33+
trackEvent: (event: Record<string, unknown>) => mockTrackEvent(event),
34+
},
35+
}));
36+
2437
// Enable fake timers globally for this test file
2538
jest.useFakeTimers();
2639

@@ -115,6 +128,7 @@ let mockSetShowError: jest.Mock;
115128
let mockShowError = false;
116129

117130
beforeEach(() => {
131+
mockTrackEvent.mockClear();
118132
mockSetShowError = jest.fn((value) => {
119133
mockShowError = value;
120134
});
@@ -259,17 +273,7 @@ describe('PaymentRequest', () => {
259273

260274
describe('handleNetworkPickerPress', () => {
261275
it('should navigate to network selector modal when feature flag is enabled', () => {
262-
const mockMetrics = {
263-
trackEvent: jest.fn(),
264-
createEventBuilder: jest.fn(() => ({
265-
addProperties: jest.fn(() => ({
266-
build: jest.fn(() => 'builtEvent'),
267-
})),
268-
})),
269-
};
270-
271276
const { getByTestId } = renderComponent({
272-
metrics: mockMetrics,
273277
chainId: '0x1',
274278
networkImageSource: ethLogo,
275279
});

0 commit comments

Comments
 (0)