Skip to content

Commit baf216a

Browse files
committed
test(home): cover action grid analytics and grey-out
Disable Buy when the account cannot sign, matching FundActionMenu, and expand grid unit tests for all eight button clicks and flag gates.
1 parent a82b411 commit baf216a

2 files changed

Lines changed: 201 additions & 62 deletions

File tree

app/components/Views/Homepage/components/HomepageActionButtonsGrid/HomepageActionButtonsGrid.test.tsx

Lines changed: 197 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -80,41 +80,100 @@ jest.mock('react-redux', () => ({
8080

8181
import HomepageActionButtonsGrid from './HomepageActionButtonsGrid';
8282

83-
const mockSelectorState = () => {
83+
interface SelectorOverrides {
84+
canSignTransactions?: boolean;
85+
isSwapsEnabled?: boolean;
86+
isBatchSellEnabled?: boolean;
87+
isSocialLeaderboardEnabled?: boolean;
88+
isPerpsEnabled?: boolean;
89+
isPredictEnabled?: boolean;
90+
isFirstTimePerpsUser?: boolean;
91+
}
92+
93+
const mockSelectorState = (overrides: SelectorOverrides = {}) => {
94+
const {
95+
canSignTransactions = true,
96+
isSwapsEnabled = true,
97+
isBatchSellEnabled = true,
98+
isSocialLeaderboardEnabled = true,
99+
isPerpsEnabled = true,
100+
isPredictEnabled = true,
101+
isFirstTimePerpsUser = false,
102+
} = overrides;
103+
84104
mockUseSelector.mockImplementation((selector: unknown) => {
85105
if (selector === selectCanSignTransactions) {
86-
return true;
106+
return canSignTransactions;
87107
}
88108
if (selector === selectIsSwapsEnabled) {
89-
return true;
109+
return isSwapsEnabled;
90110
}
91111
if (selector === selectBatchSellEnabled) {
92-
return true;
112+
return isBatchSellEnabled;
93113
}
94114
if (selector === selectSocialLeaderboardEnabled) {
95-
return true;
115+
return isSocialLeaderboardEnabled;
96116
}
97117
if (selector === selectPerpsEnabledFlag) {
98-
return true;
118+
return isPerpsEnabled;
99119
}
100120
if (selector === selectIsFirstTimePerpsUser) {
101-
return false;
121+
return isFirstTimePerpsUser;
102122
}
103123
if (selector === selectPredictEnabledFlag) {
104-
return true;
124+
return isPredictEnabled;
105125
}
106-
// selectIsSwapsEnabled is often called as (state) => select...(state)
126+
// Swap / Batch Swap wrap selectIsSwapsEnabled in an arrow selector.
107127
if (typeof selector === 'function') {
108-
try {
109-
return selector({});
110-
} catch {
111-
return true;
112-
}
128+
return isSwapsEnabled;
113129
}
114130
return true;
115131
});
116132
};
117133

134+
const ROW1_TOP_BUTTON_CASES = [
135+
{
136+
testId: HomepageActionButtonsGridTestIds.BUY_BUTTON,
137+
actionName: ActionButtonType.BUY,
138+
actionPosition: ActionPosition.FIRST_POSITION,
139+
},
140+
{
141+
testId: HomepageActionButtonsGridTestIds.SELL_BUTTON,
142+
actionName: ActionButtonType.SELL,
143+
actionPosition: ActionPosition.SECOND_POSITION,
144+
},
145+
{
146+
testId: HomepageActionButtonsGridTestIds.SWAP_BUTTON,
147+
actionName: ActionButtonType.SWAP,
148+
actionPosition: ActionPosition.THIRD_POSITION,
149+
},
150+
{
151+
testId: HomepageActionButtonsGridTestIds.SEND_BUTTON,
152+
actionName: ActionButtonType.SEND,
153+
actionPosition: ActionPosition.FOURTH_POSITION,
154+
},
155+
{
156+
testId: HomepageActionButtonsGridTestIds.PERPS_BUTTON,
157+
actionName: ActionButtonType.PERPS,
158+
actionPosition: ActionPosition.FIFTH_POSITION,
159+
},
160+
{
161+
testId: HomepageActionButtonsGridTestIds.PREDICT_BUTTON,
162+
actionName: ActionButtonType.PREDICT,
163+
actionPosition: ActionPosition.SIXTH_POSITION,
164+
},
165+
{
166+
testId: HomepageActionButtonsGridTestIds.BATCH_SWAP_BUTTON,
167+
actionName: ActionButtonType.BATCH_SWAP,
168+
actionPosition: ActionPosition.SEVENTH_POSITION,
169+
},
170+
{
171+
testId: HomepageActionButtonsGridTestIds.TRADERS_BUTTON,
172+
actionName: ActionButtonType.TRADERS,
173+
actionPosition: ActionPosition.EIGHTH_POSITION,
174+
},
175+
] as const;
176+
118177
describe('HomepageActionButtonsGrid', () => {
119178
beforeEach(() => {
120179
jest.clearAllMocks();
@@ -129,50 +188,31 @@ describe('HomepageActionButtonsGrid', () => {
129188
expect(
130189
getByTestId(HomepageActionButtonsGridTestIds.CONTAINER),
131190
).toBeOnTheScreen();
132-
expect(
133-
getByTestId(HomepageActionButtonsGridTestIds.BUY_BUTTON),
134-
).toBeOnTheScreen();
135-
expect(
136-
getByTestId(HomepageActionButtonsGridTestIds.SELL_BUTTON),
137-
).toBeOnTheScreen();
138-
expect(
139-
getByTestId(HomepageActionButtonsGridTestIds.SWAP_BUTTON),
140-
).toBeOnTheScreen();
141-
expect(
142-
getByTestId(HomepageActionButtonsGridTestIds.SEND_BUTTON),
143-
).toBeOnTheScreen();
144-
expect(
145-
getByTestId(HomepageActionButtonsGridTestIds.PERPS_BUTTON),
146-
).toBeOnTheScreen();
147-
expect(
148-
getByTestId(HomepageActionButtonsGridTestIds.PREDICT_BUTTON),
149-
).toBeOnTheScreen();
150-
expect(
151-
getByTestId(HomepageActionButtonsGridTestIds.BATCH_SWAP_BUTTON),
152-
).toBeOnTheScreen();
153-
expect(
154-
getByTestId(HomepageActionButtonsGridTestIds.TRADERS_BUTTON),
155-
).toBeOnTheScreen();
191+
ROW1_TOP_BUTTON_CASES.forEach(({ testId }) => {
192+
expect(getByTestId(testId)).toBeOnTheScreen();
193+
});
156194
});
157195

158-
it('tracks sell tap with second position for row1Top', () => {
159-
const { getByTestId } = render(
160-
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
161-
);
196+
it.each(ROW1_TOP_BUTTON_CASES)(
197+
'tracks $actionName tap with position $actionPosition for row1Top',
198+
({ testId, actionName, actionPosition }) => {
199+
const { getByTestId } = render(
200+
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
201+
);
162202

163-
fireEvent.press(getByTestId(HomepageActionButtonsGridTestIds.SELL_BUTTON));
203+
fireEvent.press(getByTestId(testId));
164204

165-
expect(mockTrackActionButtonClick).toHaveBeenCalledWith(
166-
expect.anything(),
167-
expect.anything(),
168-
expect.objectContaining({
169-
action_name: ActionButtonType.SELL,
170-
action_position: ActionPosition.SECOND_POSITION,
171-
location: ActionLocation.HOME,
172-
}),
173-
);
174-
expect(mockGoToSell).toHaveBeenCalledTimes(1);
175-
});
205+
expect(mockTrackActionButtonClick).toHaveBeenCalledWith(
206+
expect.anything(),
207+
expect.anything(),
208+
expect.objectContaining({
209+
action_name: actionName,
210+
action_position: actionPosition,
211+
location: ActionLocation.HOME,
212+
}),
213+
);
214+
},
215+
);
176216

177217
it('tracks sell tap with sixth position for row2Top', () => {
178218
const { getByTestId } = render(
@@ -200,13 +240,108 @@ describe('HomepageActionButtonsGrid', () => {
200240
fireEvent.press(getByTestId(HomepageActionButtonsGridTestIds.SEND_BUTTON));
201241

202242
expect(mockOnSend).toHaveBeenCalledTimes(1);
203-
expect(mockTrackActionButtonClick).toHaveBeenCalledWith(
204-
expect.anything(),
205-
expect.anything(),
206-
expect.objectContaining({
207-
action_name: ActionButtonType.SEND,
208-
action_position: ActionPosition.FOURTH_POSITION,
209-
}),
210-
);
243+
});
244+
245+
describe('grey-out when product flags are off', () => {
246+
it('disables buy and sell when account cannot sign', () => {
247+
mockSelectorState({ canSignTransactions: false });
248+
249+
const { getByTestId } = render(
250+
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
251+
);
252+
253+
expect(
254+
getByTestId(HomepageActionButtonsGridTestIds.BUY_BUTTON).props
255+
.accessibilityState,
256+
).toMatchObject({ disabled: true });
257+
expect(
258+
getByTestId(HomepageActionButtonsGridTestIds.SELL_BUTTON).props
259+
.accessibilityState,
260+
).toMatchObject({ disabled: true });
261+
expect(
262+
getByTestId(HomepageActionButtonsGridTestIds.SEND_BUTTON).props
263+
.accessibilityState,
264+
).toMatchObject({ disabled: true });
265+
});
266+
267+
it('disables swap when swaps are disabled', () => {
268+
mockSelectorState({ isSwapsEnabled: false });
269+
270+
const { getByTestId } = render(
271+
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
272+
);
273+
274+
expect(
275+
getByTestId(HomepageActionButtonsGridTestIds.SWAP_BUTTON).props
276+
.accessibilityState,
277+
).toMatchObject({ disabled: true });
278+
});
279+
280+
it('disables perps when perps flag is off', () => {
281+
mockSelectorState({ isPerpsEnabled: false });
282+
283+
const { getByTestId } = render(
284+
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
285+
);
286+
287+
expect(
288+
getByTestId(HomepageActionButtonsGridTestIds.PERPS_BUTTON).props
289+
.accessibilityState,
290+
).toMatchObject({ disabled: true });
291+
});
292+
293+
it('disables predict when predict flag is off', () => {
294+
mockSelectorState({ isPredictEnabled: false });
295+
296+
const { getByTestId } = render(
297+
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
298+
);
299+
300+
expect(
301+
getByTestId(HomepageActionButtonsGridTestIds.PREDICT_BUTTON).props
302+
.accessibilityState,
303+
).toMatchObject({ disabled: true });
304+
});
305+
306+
it('disables batch swap when batch sell flag is off', () => {
307+
mockSelectorState({ isBatchSellEnabled: false });
308+
309+
const { getByTestId } = render(
310+
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
311+
);
312+
313+
expect(
314+
getByTestId(HomepageActionButtonsGridTestIds.BATCH_SWAP_BUTTON).props
315+
.accessibilityState,
316+
).toMatchObject({ disabled: true });
317+
});
318+
319+
it('disables traders when social leaderboard flag is off', () => {
320+
mockSelectorState({ isSocialLeaderboardEnabled: false });
321+
322+
const { getByTestId } = render(
323+
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
324+
);
325+
326+
expect(
327+
getByTestId(HomepageActionButtonsGridTestIds.TRADERS_BUTTON).props
328+
.accessibilityState,
329+
).toMatchObject({ disabled: true });
330+
});
331+
332+
it('does not track or navigate when a disabled button is pressed', () => {
333+
mockSelectorState({ isPerpsEnabled: false });
334+
335+
const { getByTestId } = render(
336+
<HomepageActionButtonsGrid onSend={mockOnSend} rowOrder="row1Top" />,
337+
);
338+
339+
fireEvent.press(
340+
getByTestId(HomepageActionButtonsGridTestIds.PERPS_BUTTON),
341+
);
342+
343+
expect(mockTrackActionButtonClick).not.toHaveBeenCalled();
344+
expect(mockNavigate).not.toHaveBeenCalled();
345+
});
211346
});
212347
});

app/components/Views/Homepage/components/HomepageActionButtonsGrid/buttons/BuyButton.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, { useCallback } from 'react';
2+
import { useSelector } from 'react-redux';
23
import { IconName } from '@metamask/design-system-react-native';
34
import { strings } from '../../../../../../../locales/i18n';
5+
import { selectCanSignTransactions } from '../../../../../../selectors/accountsController';
46
import { useAnalytics } from '../../../../../hooks/useAnalytics/useAnalytics';
57
import { useRampNavigation } from '../../../../../UI/Ramp/hooks/useRampNavigation';
68
import {
@@ -18,6 +20,7 @@ const BuyButton = ({
1820
}: HomepageActionButtonSlotProps) => {
1921
const { trackEvent, createEventBuilder } = useAnalytics();
2022
const { goToBuy } = useRampNavigation();
23+
const canSignTransactions = useSelector(selectCanSignTransactions);
2124
const label = strings('homepage.action_buttons.buy');
2225

2326
const handlePress = useCallback(() => {
@@ -34,6 +37,7 @@ const BuyButton = ({
3437
<HomepageActionButton
3538
allowTwoLineLabel={allowTwoLineLabel}
3639
iconName={IconName.Add}
40+
isDisabled={!canSignTransactions}
3741
label={label}
3842
onPress={handlePress}
3943
testID={HomepageActionButtonsGridTestIds.BUY_BUTTON}

0 commit comments

Comments
 (0)