Skip to content

Commit af94ad0

Browse files
fix: update marketing traits when tracked settings change [PR 1/2] (#13254)
## **Description** >[!important] > This PR is the first of two. > In order to have small scope PRs and limit the amount of changes, the work is split into two PRs. > This PR mainly deals with the changes about marketing consent analytics. > It can be merged independently from 2/2. - moves marketing traits to global `generateUserProfileAnalyticsMetaData` user traits function - makes marketing traits use ON or OFF values for consistency with other user profile traits. - removes `is_metrics_opted_in` from user profile traits as we don't have consistent data anyway and the fact that data is tracked means use opted in. - the user optin (metrics enabled or not) remains unchanged in the app and is stored to know if events should be tracked or not. - If user optin is not set at onboarding, it can be updated in settings. - adds unit tests for `generateUserProfileAnalyticsMetaData` function - update other unit tests ## **Related issues** Fixes part 1/2 of MetaMask/mobile-planning#1459 ## **Manual testing steps** ```gherkin Feature: update marketing consent in user profile when it changes Scenario: user accepts marketing during onboarding Given a fresh install of the app When user accepts metametrics during onboarding And user accepts marketing consent Then you have IDENTIFY event sent And identify event contains "has_marketing_consent" trait with value "ON" And you have TRACK event sent And track event has "has_marketing_consent" prop set to "true" And track event has "location" prop set to "onboarding_metametrics" And track event has "updated_after_onboarding" prop set to "false" Scenario: user refuses marketing during onboarding Given a fresh install of the app When user accepts metametrics during onboarding And user refuses marketing consent (leave checkbox unchecked) Then you have IDENTIFY event sent And identify event contains "has_marketing_consent" trait with value "OFF" And you have TRACK event sent And track event has "has_marketing_consent" prop set to "false" And track event has "location" prop set to "onboarding_metametrics" And track event has "updated_after_onboarding" prop set to "false" Scenario: user accepts marketing in settings after onboarding Given an already onboarded app And user opted in for metrics And user navigates to privacy&security settings When user activates "data collection for marketing" Then you have IDENTIFY event sent And identify event contains "has_marketing_consent" trait with value "ON" And you have TRACK event sent And track event has "has_marketing_consent" prop set to "true" And track event has "location" prop set to "settings" And track event has "updated_after_onboarding" prop set to "true" Scenario: user refuses marketing in settings after onboarding Given an already onboarded app And user opted in for metrics And user navigates to privacy&security settings When user activates "data collection for marketing" Then you have IDENTIFY event sent And identify event contains "has_marketing_consent" trait with value "OFF" And you have TRACK event sent And track event has "has_marketing_consent" prop set to "false" And track event has "location" prop set to "settings" And track event has "updated_after_onboarding" prop set to "true" ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** ``` INFO IDENTIFY event saved {"traits": {"Batch account balance requests": "ON", "Enable OpenSea API": "ON", "NFT Autodetection": "ON", "Theme": "light", "applicationVersion": "7.37.1", "currentBuildNumber": "1520", "deviceBrand": "Apple", "has_marketing_consent": true, "operatingSystemVersion": "18.2", "platform": "ios", "security_providers": "blockaid", "token_detection_enable": "ON"}, "type": "identify", "userId": "c82a0d7b-599c-4526-8dd7-cd3a35b863fd"} ``` ### **After** #### Onboarding <img width="182" alt="image" src="https://github.com/user-attachments/assets/133037f9-f0b6-4c49-b673-cec005757568" /> When user check the box for collection for marketing in onboarding ``` INFO TRACK event saved {"event": "Analytics Preference Selected", "properties": {"has_marketing_consent": true, "is_metrics_opted_in": true, "location": "onboarding_metametrics", "updated_after_onboarding": false}, "type": "track"} INFO IDENTIFY event saved {"traits": {"Batch account balance requests": "ON", "Enable OpenSea API": "ON", "NFT Autodetection": "ON", "Theme": "light", "applicationVersion": "7.37.1", "currentBuildNumber": "1520", "deviceBrand": "Apple", "has_marketing_consent": "ON", "operatingSystemVersion": "18.2", "platform": "ios", "security_providers": "blockaid", "token_detection_enable": "ON"}, "type": "identify", "userId": "e142a0a5-670b-4f74-b531-b207bf0576d4"} ``` #### Settings <img width="182" alt="image" src="https://github.com/user-attachments/assets/6b520c52-b62c-42e1-99e6-d1e21fe303c3" /> When user switches ON data collection for marketing in settings ``` INFO IDENTIFY event saved {"traits": {"has_marketing_consent": "ON"}, "type": "identify", "userId": "ba888bd9-92cc-4783-a1c6-b72aaeadccab"} INFO TRACK event saved {"event": "Analytics Preference Selected", "properties": {"has_marketing_consent": true, "location": "settings", "updated_after_onboarding": true}, "type": "track"} ``` When user switches OFF data collection for marketing in settings ``` INFO IDENTIFY event saved {"traits": {"has_marketing_consent": "OFF"}, "type": "identify", "userId": "ba888bd9-92cc-4783-a1c6-b72aaeadccab"} INFO TRACK event saved {"event": "Analytics Preference Selected", "properties": {"has_marketing_consent": false, "location": "settings", "updated_after_onboarding": true}, "type": "track"} ``` #### Marketing modal <img width="182" alt="image" src="https://github.com/user-attachments/assets/87b92f34-57ab-49c5-a3ea-38d3ac374a81" /> When user touches "no thanks" ``` INFO IDENTIFY event saved {"traits": {"has_marketing_consent": "OFF"}, "type": "identify", "userId": "e142a0a5-670b-4f74-b531-b207bf0576d4"} INFO TRACK event saved {"event": "Analytics Preference Selected", "properties": {"has_marketing_consent": false, "location": "marketing_consent_modal", "updated_after_onboarding": true}, "type": "track"} ``` When user touches "I agree" ``` INFO IDENTIFY event saved {"traits": {"has_marketing_consent": "ON"}, "type": "identify", "userId": "e142a0a5-670b-4f74-b531-b207bf0576d4"} INFO TRACK event saved {"event": "Analytics Preference Selected", "properties": {"has_marketing_consent": true, "location": "marketing_consent_modal", "updated_after_onboarding": true}, "type": "track"} ``` ## **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.
1 parent f36b02f commit af94ad0

File tree

9 files changed

+149
-60
lines changed

9 files changed

+149
-60
lines changed

app/components/UI/OptinMetrics/index.js

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ import Routes from '../../../constants/navigation/Routes';
4040
import generateDeviceAnalyticsMetaData, {
4141
UserSettingsAnalyticsMetaData as generateUserSettingsAnalyticsMetaData,
4242
} from '../../../util/metrics';
43+
import {
44+
UserProfileProperty
45+
} from '../../../util/metrics/UserSettingsAnalyticsMetaData/UserProfileAnalyticsMetaData.types';
4346

4447
const createStyles = ({ colors }) =>
4548
StyleSheet.create({
@@ -338,44 +341,33 @@ class OptinMetrics extends PureComponent {
338341
setDataCollectionForMarketing,
339342
} = this.props;
340343

341-
// Set marketing consent trait based on user selection
342-
const dataCollectionForMarketingTraits = {
343-
has_marketing_consent: Boolean(
344-
this.props.isDataCollectionForMarketingEnabled,
345-
),
346-
};
347-
348344
await metrics.enable();
349345

346+
// Handle null case for marketing consent
347+
if (
348+
isDataCollectionForMarketingEnabled === null &&
349+
setDataCollectionForMarketing
350+
) {
351+
setDataCollectionForMarketing(false);
352+
}
353+
350354
// Track the analytics preference event first
351355
metrics.trackEvent(
352356
metrics
353357
.createEventBuilder(MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED)
354358
.addProperties({
355-
...dataCollectionForMarketingTraits,
356-
is_metrics_opted_in: true,
357-
location: 'onboarding_metametrics',
358-
updated_after_onboarding: false,
359+
[UserProfileProperty.HAS_MARKETING_CONSENT]: Boolean( isDataCollectionForMarketingEnabled ),
360+
is_metrics_opted_in: true,
361+
location: 'onboarding_metametrics',
362+
updated_after_onboarding: false,
359363
})
360364
.build(),
361365
);
362366

363-
// Handle null case for marketing consent
364-
if (
365-
isDataCollectionForMarketingEnabled === null &&
366-
setDataCollectionForMarketing
367-
) {
368-
setDataCollectionForMarketing(false);
369-
}
370-
371-
// consolidate device and user settings traits
372-
const consolidatedTraits = {
373-
...dataCollectionForMarketingTraits,
374-
is_metrics_opted_in: true,
375-
...generateDeviceAnalyticsMetaData(),
376-
...generateUserSettingsAnalyticsMetaData(),
377-
};
378-
await metrics.addTraitsToUser(consolidatedTraits);
367+
await metrics.addTraitsToUser({
368+
...generateDeviceAnalyticsMetaData(),
369+
...generateUserSettingsAnalyticsMetaData(),
370+
});
379371

380372
// track onboarding events that were stored before user opted in
381373
// only if the user eventually opts in.

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ describe('OptinMetrics', () => {
7575
expect(mockMetrics.addTraitsToUser).toHaveBeenNthCalledWith(1, {
7676
deviceProp: 'Device value',
7777
userProp: 'User value',
78-
is_metrics_opted_in: true,
79-
has_marketing_consent: false,
8078
});
8179
});
8280
});
@@ -106,8 +104,6 @@ describe('OptinMetrics', () => {
106104
expect(mockMetrics.addTraitsToUser).toHaveBeenNthCalledWith(1, {
107105
deviceProp: 'Device value',
108106
userProp: 'User value',
109-
is_metrics_opted_in: true,
110-
has_marketing_consent: true,
111107
});
112108
});
113109
});

app/components/Views/ExperienceEnhancerModal/index.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import {
2525
} from '../../../components/hooks/useMetrics';
2626
import { HOW_TO_MANAGE_METRAMETRICS_SETTINGS } from '../../../constants/urls';
2727
import { ExperienceEnhancerBottomSheetSelectorsIDs } from '../../../../e2e/selectors/Onboarding/ExperienceEnhancerModal.selectors.js';
28+
import {
29+
UserProfileProperty
30+
} from '../../../util/metrics/UserSettingsAnalyticsMetaData/UserProfileAnalyticsMetaData.types';
2831

2932
const ExperienceEnhancerModal = () => {
3033
const dispatch = useDispatch();
@@ -40,14 +43,14 @@ const ExperienceEnhancerModal = () => {
4043
dispatch(setDataCollectionForMarketing(false));
4144
bottomSheetRef.current?.onCloseBottomSheet();
4245

43-
const traits = {
44-
has_marketing_consent: false,
45-
};
46-
addTraitsToUser(traits);
46+
addTraitsToUser({
47+
[UserProfileProperty.HAS_MARKETING_CONSENT]: UserProfileProperty.OFF,
48+
});
4749
trackEvent(
4850
createEventBuilder(MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED)
4951
.addProperties({
50-
...traits,
52+
[UserProfileProperty.HAS_MARKETING_CONSENT]: false,
53+
updated_after_onboarding: true,
5154
location: 'marketing_consent_modal',
5255
})
5356
.build(),
@@ -64,12 +67,14 @@ const ExperienceEnhancerModal = () => {
6467
dispatch(setDataCollectionForMarketing(true));
6568
bottomSheetRef.current?.onCloseBottomSheet();
6669

67-
const traits = { has_marketing_consent: true };
68-
addTraitsToUser(traits);
70+
addTraitsToUser({
71+
[UserProfileProperty.HAS_MARKETING_CONSENT]: UserProfileProperty.ON,
72+
});
6973
trackEvent(
7074
createEventBuilder(MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED)
7175
.addProperties({
72-
...traits,
76+
[UserProfileProperty.HAS_MARKETING_CONSENT]: true,
77+
updated_after_onboarding: true,
7378
location: 'marketing_consent_modal',
7479
})
7580
.build(),

app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.test.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ describe('MetaMetricsAndDataCollectionSection', () => {
210210
expect(mockMetrics.addTraitsToUser).toHaveBeenCalledWith({
211211
deviceProp: 'Device value',
212212
userProp: 'User value',
213-
is_metrics_opted_in: true,
214213
});
215214
expect(mockMetrics.trackEvent).toHaveBeenCalledWith(
216215
MetricsEventBuilder.createEventBuilder(
@@ -219,6 +218,7 @@ describe('MetaMetricsAndDataCollectionSection', () => {
219218
.addProperties({
220219
is_metrics_opted_in: true,
221220
updated_after_onboarding: true,
221+
location: 'settings',
222222
})
223223
.build(),
224224
);
@@ -299,7 +299,6 @@ describe('MetaMetricsAndDataCollectionSection', () => {
299299
expect(mockMetrics.addTraitsToUser).toHaveBeenNthCalledWith(1, {
300300
deviceProp: 'Device value',
301301
userProp: 'User value',
302-
is_metrics_opted_in: true,
303302
});
304303
expect(mockMetrics.trackEvent).toHaveBeenNthCalledWith(
305304
1,
@@ -308,6 +307,7 @@ describe('MetaMetricsAndDataCollectionSection', () => {
308307
)
309308
.addProperties({
310309
is_metrics_opted_in: true,
310+
location: 'settings',
311311
updated_after_onboarding: true,
312312
})
313313
.build(),
@@ -318,7 +318,7 @@ describe('MetaMetricsAndDataCollectionSection', () => {
318318
// if MetaMetrics is initially disabled, addTraitsToUser is called twice and this is 2nd call
319319
!metaMetricsInitiallyEnabled ? 2 : 1,
320320
{
321-
has_marketing_consent: true,
321+
has_marketing_consent: 'ON',
322322
},
323323
);
324324
expect(mockMetrics.trackEvent).toHaveBeenNthCalledWith(
@@ -330,6 +330,7 @@ describe('MetaMetricsAndDataCollectionSection', () => {
330330
.addProperties({
331331
has_marketing_consent: true,
332332
location: 'settings',
333+
updated_after_onboarding: true,
333334
})
334335
.build(),
335336
);
@@ -376,7 +377,7 @@ describe('MetaMetricsAndDataCollectionSection', () => {
376377
expect(mockAlert).not.toHaveBeenCalled();
377378
expect(mockMetrics.addTraitsToUser).toHaveBeenCalledTimes(1);
378379
expect(mockMetrics.addTraitsToUser).toHaveBeenCalledWith({
379-
has_marketing_consent: false,
380+
has_marketing_consent: 'OFF',
380381
});
381382
expect(mockMetrics.trackEvent).toHaveBeenCalledTimes(1);
382383
expect(mockMetrics.trackEvent).toHaveBeenCalledWith(
@@ -386,6 +387,7 @@ describe('MetaMetricsAndDataCollectionSection', () => {
386387
.addProperties({
387388
has_marketing_consent: false,
388389
location: 'settings',
390+
updated_after_onboarding: true,
389391
})
390392
.build(),
391393
);

app/components/Views/Settings/SecuritySettings/Sections/MetaMetricsAndDataCollectionSection/MetaMetricsAndDataCollectionSection.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ import Routes from '../../../../../../constants/navigation/Routes';
2626
import { useMetrics } from '../../../../../hooks/useMetrics';
2727
import { useDispatch, useSelector } from 'react-redux';
2828
import { useNavigation } from '@react-navigation/native';
29+
import {
30+
UserProfileProperty
31+
} from '../../../../../../util/metrics/UserSettingsAnalyticsMetaData/UserProfileAnalyticsMetaData.types';
2932

3033
const MetaMetricsAndDataCollectionSection: React.FC = () => {
3134
const theme = useTheme();
@@ -51,7 +54,6 @@ const MetaMetricsAndDataCollectionSection: React.FC = () => {
5154
const consolidatedTraits = {
5255
...generateDeviceAnalyticsMetaData(),
5356
...generateUserSettingsAnalyticsMetaData(),
54-
is_metrics_opted_in: true,
5557
};
5658
await enable();
5759
setAnalyticsEnabled(true);
@@ -63,6 +65,7 @@ const MetaMetricsAndDataCollectionSection: React.FC = () => {
6365
.addProperties({
6466
is_metrics_opted_in: true,
6567
updated_after_onboarding: true,
68+
location: 'settings',
6669
})
6770
.build(),
6871
);
@@ -82,14 +85,14 @@ const MetaMetricsAndDataCollectionSection: React.FC = () => {
8285

8386
const addMarketingConsentToTraits = (marketingOptIn: boolean) => {
8487
InteractionManager.runAfterInteractions(async () => {
85-
const traits = {
86-
has_marketing_consent: marketingOptIn,
87-
};
88-
await addTraitsToUser(traits);
88+
await addTraitsToUser({
89+
[UserProfileProperty.HAS_MARKETING_CONSENT]: marketingOptIn ? UserProfileProperty.ON : UserProfileProperty.OFF,
90+
});
8991
trackEvent(
9092
createEventBuilder(MetaMetricsEvents.ANALYTICS_PREFERENCE_SELECTED)
9193
.addProperties({
92-
...traits,
94+
[UserProfileProperty.HAS_MARKETING_CONSENT]: marketingOptIn,
95+
updated_after_onboarding: true,
9396
location: 'settings',
9497
})
9598
.build(),

app/core/AppStateEventListener.test.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ jest.mock('./processAttribution', () => ({
1616
processAttribution: jest.fn(),
1717
}));
1818

19+
jest.mock(
20+
'../util/metrics/UserSettingsAnalyticsMetaData/generateUserProfileAnalyticsMetaData',
21+
() => jest.fn().mockReturnValue({ userProp: 'User value' }),
22+
);
23+
24+
jest.mock(
25+
'../util/metrics/DeviceAnalyticsMetaData/generateDeviceAnalyticsMetaData',
26+
() => jest.fn().mockReturnValue({ deviceProp: 'Device value' }),
27+
);
28+
1929
jest.mock('./Analytics/MetaMetrics');
2030

2131
const mockMetrics = {
@@ -115,17 +125,8 @@ describe('AppStateEventListener', () => {
115125

116126
expect(mockMetrics.addTraitsToUser).toHaveBeenCalledTimes(1);
117127
expect(mockMetrics.addTraitsToUser).toHaveBeenCalledWith({
118-
'Batch account balance requests': 'OFF',
119-
'Enable OpenSea API': 'OFF',
120-
'NFT Autodetection': 'OFF',
121-
'Theme': undefined,
122-
'applicationVersion': expect.any(Promise),
123-
'currentBuildNumber': expect.any(Promise),
124-
'deviceBrand': 'Apple',
125-
'operatingSystemVersion': 'ios',
126-
'platform': 'ios',
127-
'security_providers': '',
128-
'token_detection_enable': 'OFF',
128+
deviceProp: 'Device value',
129+
userProp: 'User value',
129130
});
130131
});
131132

app/util/metrics/UserSettingsAnalyticsMetaData/UserProfileAnalyticsMetaData.types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export enum UserProfileProperty {
1010
SECURITY_PROVIDERS = 'security_providers',
1111
PRIMARY_CURRENCY = 'primary_currency',
1212
CURRENT_CURRENCY = 'current_currency',
13+
HAS_MARKETING_CONSENT = 'has_marketing_consent',
1314
}
1415

1516
export interface UserProfileMetaData {
@@ -22,4 +23,5 @@ export interface UserProfileMetaData {
2223
[UserProfileProperty.SECURITY_PROVIDERS]: string;
2324
[UserProfileProperty.PRIMARY_CURRENCY]?: string;
2425
[UserProfileProperty.CURRENT_CURRENCY]?: string;
26+
[UserProfileProperty.HAS_MARKETING_CONSENT]: string;
2527
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import generateUserProfileAnalyticsMetaData from './generateUserProfileAnalyticsMetaData';
2+
import { UserProfileProperty } from './UserProfileAnalyticsMetaData.types';
3+
import {Appearance} from 'react-native';
4+
5+
const mockGetState = jest.fn();
6+
jest.mock('../../../store', () => ({
7+
store: {
8+
getState: jest.fn(() => mockGetState()),
9+
},
10+
}));
11+
12+
const mockIsMetricsEnabled = jest.fn();
13+
jest.mock('../../../core/Analytics', () => ({
14+
MetaMetrics: {
15+
getInstance: jest.fn(() => ({ isEnabled: mockIsMetricsEnabled })),
16+
},
17+
}));
18+
19+
jest.spyOn(Appearance, 'getColorScheme').mockReturnValue('dark');
20+
21+
describe('generateUserProfileAnalyticsMetaData', () => {
22+
const mockState = {
23+
engine: {
24+
backgroundState: {
25+
PreferencesController: {
26+
displayNftMedia: true,
27+
useNftDetection: false,
28+
useTokenDetection: true,
29+
isMultiAccountBalancesEnabled: false,
30+
securityAlertsEnabled: true,
31+
},
32+
},
33+
},
34+
user: { appTheme: 'os' },
35+
security: { dataCollectionForMarketing: true },
36+
};
37+
38+
it('returns metadata', () => {
39+
mockGetState.mockReturnValue(mockState);
40+
mockIsMetricsEnabled.mockReturnValue(true);
41+
42+
const metadata = generateUserProfileAnalyticsMetaData();
43+
expect(metadata).toEqual({
44+
[UserProfileProperty.ENABLE_OPENSEA_API]: UserProfileProperty.ON,
45+
[UserProfileProperty.NFT_AUTODETECTION]: UserProfileProperty.OFF,
46+
[UserProfileProperty.THEME]: 'dark',
47+
[UserProfileProperty.TOKEN_DETECTION]: UserProfileProperty.ON,
48+
[UserProfileProperty.MULTI_ACCOUNT_BALANCE]: UserProfileProperty.OFF,
49+
[UserProfileProperty.SECURITY_PROVIDERS]: 'blockaid',
50+
[UserProfileProperty.HAS_MARKETING_CONSENT]: UserProfileProperty.ON,
51+
});
52+
});
53+
54+
it.each([
55+
[UserProfileProperty.ON, true],
56+
[UserProfileProperty.OFF, false],
57+
])('returns marketing consent "%s"', (expected, stateConsentValue) => {
58+
mockGetState.mockReturnValue({ ...mockState, security: { dataCollectionForMarketing: stateConsentValue } });
59+
60+
const metadata = generateUserProfileAnalyticsMetaData();
61+
expect(metadata[UserProfileProperty.HAS_MARKETING_CONSENT]).toEqual(expected);
62+
});
63+
64+
it('returns default metadata when missing preferences controller', () => {
65+
mockGetState.mockReturnValue({ ...mockState, engine: {} });
66+
67+
const metadata = generateUserProfileAnalyticsMetaData();
68+
expect(metadata).toMatchObject({
69+
[UserProfileProperty.ENABLE_OPENSEA_API]: UserProfileProperty.OFF,
70+
[UserProfileProperty.NFT_AUTODETECTION]: UserProfileProperty.OFF,
71+
[UserProfileProperty.TOKEN_DETECTION]: UserProfileProperty.OFF,
72+
[UserProfileProperty.MULTI_ACCOUNT_BALANCE]: UserProfileProperty.OFF,
73+
[UserProfileProperty.SECURITY_PROVIDERS]: '',
74+
});
75+
});
76+
77+
it('returns user preference for theme', () => {
78+
mockGetState.mockReturnValue({ ...mockState, user: { appTheme: 'light' } });
79+
80+
const metadata = generateUserProfileAnalyticsMetaData();
81+
expect(metadata[UserProfileProperty.THEME]).toBe('light');
82+
});
83+
});

0 commit comments

Comments
 (0)