Skip to content

Commit d21e4e3

Browse files
authored
Merge branch 'main' into rewards-use-mobile-optin
2 parents 922af55 + e5d7c95 commit d21e4e3

File tree

7 files changed

+183
-12
lines changed

7 files changed

+183
-12
lines changed

app/actions/notification/helpers/index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@ import type { MarkAsReadNotificationsParam } from '@metamask/notification-servic
22
import Engine from '../../../core/Engine';
33
import { isNotificationsFeatureEnabled } from '../../../util/notifications';
44

5+
let previewToken: string | undefined;
6+
7+
export function setContentPreviewToken(newPreviewToken?: string | null) {
8+
if (typeof newPreviewToken === 'string') {
9+
previewToken = newPreviewToken;
10+
}
11+
}
12+
13+
export function getContentPreviewToken() {
14+
return previewToken;
15+
}
16+
517
export const assertIsFeatureEnabled = () => {
618
if (!isNotificationsFeatureEnabled()) {
719
throw new Error(
@@ -106,7 +118,9 @@ export const enableAccounts = async (accounts: string[]) => {
106118
*/
107119
export const fetchNotifications = async () => {
108120
assertIsFeatureEnabled();
109-
await Engine.context.NotificationServicesController.fetchAndUpdateMetamaskNotifications();
121+
await Engine.context.NotificationServicesController.fetchAndUpdateMetamaskNotifications(
122+
getContentPreviewToken(),
123+
);
110124
};
111125

112126
/**

app/components/UI/Carousel/fetchCarouselSlidesFromContentful.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ import { ContentfulClientApi, createClient } from 'contentful';
33
import * as DeviceInfoModule from 'react-native-device-info';
44
import {
55
fetchCarouselSlidesFromContentful,
6+
getContentfulEnvironmentDetails,
67
isActive,
78
} from './fetchCarouselSlidesFromContentful';
89
import { ACCESS_TOKEN, SPACE_ID } from './constants';
10+
import { getContentPreviewToken } from '../../../actions/notification/helpers';
11+
import { isProduction } from '../../../util/environment';
912

1013
jest.mock('contentful', () => ({
1114
createClient: jest.fn(),
@@ -17,6 +20,67 @@ jest.mock('./constants', () => ({
1720
ACCESS_TOKEN: jest.fn().mockReturnValue('mockAccessToken'),
1821
}));
1922

23+
jest.mock('../../../actions/notification/helpers');
24+
25+
jest.mock('../../../util/environment', () => ({
26+
isProduction: jest.fn().mockReturnValue(true),
27+
}));
28+
29+
describe('getContentfulEnvironmentDetails', () => {
30+
beforeEach(() => jest.clearAllMocks());
31+
32+
const arrangeMocks = () => {
33+
const mockGetContentPreviewToken = jest
34+
.mocked(getContentPreviewToken)
35+
.mockReturnValue(undefined);
36+
37+
const mockIsProduction = jest.mocked(isProduction).mockReturnValue(true);
38+
39+
return {
40+
mockGetContentPreviewToken,
41+
mockIsProduction,
42+
};
43+
};
44+
45+
it('returns preview prod environment if token provided', () => {
46+
const mocks = arrangeMocks();
47+
mocks.mockGetContentPreviewToken.mockReturnValue('AAA');
48+
49+
const result = getContentfulEnvironmentDetails();
50+
expect(result).toStrictEqual({
51+
environment: 'master',
52+
domain: 'preview.contentful.com',
53+
accessToken: 'AAA',
54+
spaceId: SPACE_ID(),
55+
});
56+
});
57+
58+
it('returns prod environment is using production', () => {
59+
arrangeMocks();
60+
61+
const result = getContentfulEnvironmentDetails();
62+
expect(result).toStrictEqual({
63+
environment: 'master',
64+
domain: 'cdn.contentful.com',
65+
accessToken: ACCESS_TOKEN(),
66+
spaceId: SPACE_ID(),
67+
});
68+
});
69+
70+
it('returns preview dev environment is not in production', () => {
71+
const mocks = arrangeMocks();
72+
mocks.mockIsProduction.mockReturnValue(false);
73+
74+
const result = getContentfulEnvironmentDetails();
75+
expect(result).toStrictEqual({
76+
environment: 'dev',
77+
domain: 'preview.contentful.com',
78+
accessToken: ACCESS_TOKEN(),
79+
spaceId: SPACE_ID(),
80+
});
81+
});
82+
});
83+
2084
describe('fetchCarouselSlidesFromContentful', () => {
2185
beforeEach(() => {
2286
jest.resetAllMocks();

app/components/UI/Carousel/fetchCarouselSlidesFromContentful.ts

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { isProduction } from '../../../util/environment';
33
import { CarouselSlide } from './types';
44
import { ACCESS_TOKEN, SPACE_ID } from './constants';
55
import { hasMinimumRequiredVersion } from '../../../util/remoteFeatureFlag';
6+
import { getContentPreviewToken } from '../../../actions/notification/helpers';
67

78
export interface ContentfulCarouselSlideFields {
89
headline: string;
@@ -20,11 +21,40 @@ export interface ContentfulCarouselSlideFields {
2021
export type ContentfulSlideSkeleton =
2122
EntrySkeletonType<ContentfulCarouselSlideFields>;
2223

23-
const ENVIRONMENT = isProduction() ? 'master' : 'dev';
24+
export const getContentfulEnvironmentDetails = () => {
25+
// If preview mode, then show preview prod master content
26+
const previewToken = getContentPreviewToken();
27+
if (previewToken) {
28+
return {
29+
environment: 'master',
30+
domain: 'preview.contentful.com',
31+
accessToken: previewToken,
32+
spaceId: SPACE_ID(),
33+
};
34+
}
35+
36+
const isProd = isProduction();
37+
38+
// If production, show prod master content
39+
if (isProd) {
40+
return {
41+
environment: 'master',
42+
domain: 'cdn.contentful.com',
43+
accessToken: ACCESS_TOKEN(),
44+
spaceId: SPACE_ID(),
45+
};
46+
}
47+
48+
// Default to preview dev content
49+
return {
50+
environment: 'dev',
51+
domain: 'preview.contentful.com',
52+
accessToken: ACCESS_TOKEN(),
53+
spaceId: SPACE_ID(),
54+
};
55+
};
56+
2457
const CONTENT_TYPE = 'promotionalBanner';
25-
const DEFAULT_DOMAIN = isProduction()
26-
? 'cdn.contentful.com'
27-
: 'preview.contentful.com';
2858

2959
interface ContentfulSysField {
3060
sys: { id: string };
@@ -34,8 +64,8 @@ export async function fetchCarouselSlidesFromContentful(): Promise<{
3464
prioritySlides: CarouselSlide[];
3565
regularSlides: CarouselSlide[];
3666
}> {
37-
const spaceId = SPACE_ID();
38-
const accessToken = ACCESS_TOKEN();
67+
const { spaceId, accessToken, environment, domain } =
68+
getContentfulEnvironmentDetails();
3969

4070
if (!spaceId || !accessToken) {
4171
console.warn(
@@ -44,14 +74,14 @@ export async function fetchCarouselSlidesFromContentful(): Promise<{
4474
return { prioritySlides: [], regularSlides: [] };
4575
}
4676

47-
const host = `https://${DEFAULT_DOMAIN}/spaces/${spaceId}/environments/${ENVIRONMENT}/entries`;
77+
const host = `https://${domain}/spaces/${spaceId}/environments/${environment}/entries`;
4878

4979
// First try through the Contentful Client
5080
try {
5181
const contentfulClient = createClient({
5282
space: spaceId,
5383
accessToken,
54-
environment: ENVIRONMENT,
84+
environment,
5585
host,
5686
});
5787

app/core/DeeplinkManager/DeeplinkManager.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import parseDeeplink from './ParseManager/parseDeeplink';
1111
import approveTransaction from './TransactionManager/approveTransaction';
1212
import { RampType } from '../../reducers/fiatOrders/types';
1313
import { handleSwapUrl } from './Handlers/handleSwapUrl';
14+
import { navigateToHomeUrl } from './Handlers/handleHomeUrl';
1415
import Routes from '../../constants/navigation/Routes';
1516
import { handleCreateAccountUrl } from './Handlers/handleCreateAccountUrl';
1617
import { handlePerpsUrl } from './Handlers/handlePerpsUrl';
@@ -104,8 +105,8 @@ class DeeplinkManager {
104105
}
105106

106107
// NOTE: open the home screen for new subdomain
107-
_handleOpenHome() {
108-
this.navigation.navigate(Routes.WALLET.HOME);
108+
_handleOpenHome(homePath?: string) {
109+
navigateToHomeUrl({ homePath });
109110
}
110111

111112
// NOTE: this will be used for new deeplink subdomain
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import NavigationService from '../../NavigationService';
2+
import { setContentPreviewToken } from '../../../actions/notification/helpers';
3+
import { navigateToHomeUrl } from './handleHomeUrl';
4+
import Routes from '../../../constants/navigation/Routes';
5+
6+
jest.mock('../../NavigationService');
7+
jest.mock('../../../actions/notification/helpers');
8+
9+
describe('navigateToHomeUrl', () => {
10+
beforeEach(() => jest.clearAllMocks());
11+
12+
const arrangeMocks = () => {
13+
const mockNavigate = jest.fn();
14+
NavigationService.navigation = {
15+
navigate: mockNavigate,
16+
} as unknown as typeof NavigationService.navigation;
17+
18+
const mockSetContentPreviewToken = jest.mocked(setContentPreviewToken);
19+
20+
return {
21+
mockNavigate,
22+
mockSetContentPreviewToken,
23+
};
24+
};
25+
26+
it('navigates to home screen without sending any query params', () => {
27+
const mocks = arrangeMocks();
28+
navigateToHomeUrl({ homePath: 'home' });
29+
30+
expect(mocks.mockSetContentPreviewToken).toHaveBeenCalledWith(null);
31+
expect(mocks.mockNavigate).toHaveBeenCalledWith(Routes.WALLET.HOME);
32+
});
33+
34+
it('sends previewToken and navigates to home screen', () => {
35+
const mocks = arrangeMocks();
36+
navigateToHomeUrl({ homePath: 'home?previewToken=ABC' });
37+
38+
expect(mocks.mockSetContentPreviewToken).toHaveBeenCalledWith('ABC');
39+
expect(mocks.mockNavigate).toHaveBeenCalledWith(Routes.WALLET.HOME);
40+
});
41+
42+
it('falls back to navigated to home sceen when no homePath', () => {
43+
const mocks = arrangeMocks();
44+
navigateToHomeUrl({ homePath: undefined });
45+
46+
expect(mocks.mockSetContentPreviewToken).toHaveBeenCalledWith(null);
47+
expect(mocks.mockNavigate).toHaveBeenCalledWith(Routes.WALLET.HOME);
48+
});
49+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import NavigationService from '../../NavigationService';
2+
import Routes from '../../../constants/navigation/Routes';
3+
import { setContentPreviewToken } from '../../../actions/notification/helpers';
4+
5+
export function navigateToHomeUrl(params: { homePath?: string }) {
6+
const { homePath } = params;
7+
const urlParams = new URLSearchParams(
8+
homePath?.includes('?') ? homePath.split('?')[1] : '',
9+
);
10+
setContentPreviewToken(urlParams.get('previewToken'));
11+
NavigationService.navigation.navigate(Routes.WALLET.HOME);
12+
}

app/core/DeeplinkManager/ParseManager/handleUniversalLink.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ async function handleUniversalLink({
173173
const depositCashPath = urlObj.href.replace(BASE_URL_ACTION, '');
174174
instance._handleDepositCash(depositCashPath);
175175
} else if (action === SUPPORTED_ACTIONS.HOME) {
176-
instance._handleOpenHome();
176+
const homePath = urlObj.href.replace(BASE_URL_ACTION, '');
177+
instance._handleOpenHome(homePath);
177178
return;
178179
} else if (action === SUPPORTED_ACTIONS.SWAP) {
179180
const swapPath = urlObj.href.replace(BASE_URL_ACTION, '');

0 commit comments

Comments
 (0)