Skip to content

Commit 39dd61d

Browse files
VGR-GITclaude
andcommitted
test(rewards): fix TS errors and expand coverage for notifications nudge
- Fix mockUseNavigationState typing (jest.fn with selector param) to resolve TS2554/TS2345/TS7006 errors in RewardsNavigator.test.tsx - Add selector-invoking default implementation so useNavigationState selector body lines are covered on every render - Add tests for all 4 campaign routes (Campaigns, ONDO, SeasonOne, Perps) to cover the isOnCampaignRoute || chain conditions - Add test for showEnableNotificationsNudge returning false (!didShowNudge branch) - Add test for sessionNotificationsNudgeShown already-set gate - Add missing loading mock to CampaignTile, useLinkAccountAddress, and useLinkAccountGroup test files to fix TypeError at runtime Co-authored-by: VGR-GIT <vangulckrik@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9173007 commit 39dd61d

4 files changed

Lines changed: 238 additions & 56 deletions

File tree

app/components/UI/Rewards/RewardsNavigator.test.tsx

Lines changed: 227 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ const mockSetOptions = jest.fn();
200200
const mockSetParams = jest.fn();
201201
const mockIsFocused = jest.fn();
202202
const mockReactReduxDispatch = jest.fn();
203-
const mockUseNavigationState = jest.fn(() => undefined);
203+
const mockUseNavigationState = jest.fn(
204+
(selector: (state: unknown) => unknown): unknown =>
205+
selector({ routes: [{}], index: 0 }),
206+
);
204207

205208
jest.mock('@react-navigation/native', () => {
206209
const actual = jest.requireActual('@react-navigation/native');
@@ -873,18 +876,19 @@ describe('RewardsNavigator', () => {
873876
closeEnableNotificationsNudge: mockCloseEnableNotificationsNudge,
874877
runAfterNotificationsEnabled: jest.fn(),
875878
});
876-
mockUseNavigationState.mockImplementation((selector) =>
877-
selector({
878-
routes: [
879-
{
880-
state: {
881-
routes: [{ name: Routes.REWARDS_CAMPAIGNS_VIEW }],
882-
index: 0,
879+
mockUseNavigationState.mockImplementation(
880+
(selector: (state: unknown) => unknown) =>
881+
selector({
882+
routes: [
883+
{
884+
state: {
885+
routes: [{ name: Routes.REWARDS_CAMPAIGNS_VIEW }],
886+
index: 0,
887+
},
883888
},
884-
},
885-
],
886-
index: 0,
887-
}),
889+
],
890+
index: 0,
891+
}),
888892
);
889893

890894
renderWithNavigation(<RewardsNavigator />);
@@ -902,18 +906,19 @@ describe('RewardsNavigator', () => {
902906
closeEnableNotificationsNudge: mockCloseEnableNotificationsNudge,
903907
runAfterNotificationsEnabled: jest.fn(),
904908
});
905-
mockUseNavigationState.mockImplementation((selector) =>
906-
selector({
907-
routes: [
908-
{
909-
state: {
910-
routes: [{ name: Routes.REWARDS_CAMPAIGNS_VIEW }],
911-
index: 0,
909+
mockUseNavigationState.mockImplementation(
910+
(selector: (state: unknown) => unknown) =>
911+
selector({
912+
routes: [
913+
{
914+
state: {
915+
routes: [{ name: Routes.REWARDS_CAMPAIGNS_VIEW }],
916+
index: 0,
917+
},
912918
},
913-
},
914-
],
915-
index: 0,
916-
}),
919+
],
920+
index: 0,
921+
}),
917922
);
918923

919924
renderWithNavigation(<RewardsNavigator />);
@@ -931,18 +936,19 @@ describe('RewardsNavigator', () => {
931936
closeEnableNotificationsNudge: mockCloseEnableNotificationsNudge,
932937
runAfterNotificationsEnabled: jest.fn(),
933938
});
934-
mockUseNavigationState.mockImplementation((selector) =>
935-
selector({
936-
routes: [
937-
{
938-
state: {
939-
routes: [{ name: Routes.REWARDS_DASHBOARD }],
940-
index: 0,
939+
mockUseNavigationState.mockImplementation(
940+
(selector: (state: unknown) => unknown) =>
941+
selector({
942+
routes: [
943+
{
944+
state: {
945+
routes: [{ name: Routes.REWARDS_DASHBOARD }],
946+
index: 0,
947+
},
941948
},
942-
},
943-
],
944-
index: 0,
945-
}),
949+
],
950+
index: 0,
951+
}),
946952
);
947953

948954
renderWithNavigation(<RewardsNavigator />);
@@ -951,6 +957,39 @@ describe('RewardsNavigator', () => {
951957
expect(mockShowEnableNotificationsNudge).not.toHaveBeenCalled();
952958
});
953959

960+
it('does not show nudge when showEnableNotificationsNudge returns false', async () => {
961+
mockUseRewardsNotificationsNudge.mockReturnValue({
962+
areNotificationsEnabled: false,
963+
canPromptToEnableNotifications: true,
964+
shouldPromptToEnableNotifications: true,
965+
showEnableNotificationsNudge: mockShowEnableNotificationsNudge,
966+
closeEnableNotificationsNudge: mockCloseEnableNotificationsNudge,
967+
runAfterNotificationsEnabled: jest.fn(),
968+
});
969+
mockShowEnableNotificationsNudge.mockReturnValue(false);
970+
mockUseNavigationState.mockImplementation(
971+
(selector: (state: unknown) => unknown) =>
972+
selector({
973+
routes: [
974+
{
975+
state: {
976+
routes: [{ name: Routes.REWARDS_CAMPAIGNS_VIEW }],
977+
index: 0,
978+
},
979+
},
980+
],
981+
index: 0,
982+
}),
983+
);
984+
985+
renderWithNavigation(<RewardsNavigator />);
986+
987+
await waitFor(() => {
988+
expect(mockShowEnableNotificationsNudge).toHaveBeenCalledTimes(1);
989+
});
990+
expect(mockCloseEnableNotificationsNudge).not.toHaveBeenCalled();
991+
});
992+
954993
it('shows nudge on campaign route and closes it when navigating away', async () => {
955994
mockUseRewardsNotificationsNudge.mockReturnValue({
956995
areNotificationsEnabled: false,
@@ -961,18 +1000,19 @@ describe('RewardsNavigator', () => {
9611000
runAfterNotificationsEnabled: jest.fn(),
9621001
});
9631002
mockShowEnableNotificationsNudge.mockReturnValue(true);
964-
mockUseNavigationState.mockImplementation((selector) =>
965-
selector({
966-
routes: [
967-
{
968-
state: {
969-
routes: [{ name: Routes.REWARDS_CAMPAIGNS_VIEW }],
970-
index: 0,
1003+
mockUseNavigationState.mockImplementation(
1004+
(selector: (state: unknown) => unknown) =>
1005+
selector({
1006+
routes: [
1007+
{
1008+
state: {
1009+
routes: [{ name: Routes.REWARDS_CAMPAIGNS_VIEW }],
1010+
index: 0,
1011+
},
9711012
},
972-
},
973-
],
974-
index: 0,
975-
}),
1013+
],
1014+
index: 0,
1015+
}),
9761016
);
9771017

9781018
const { rerender } = renderWithNavigation(<RewardsNavigator />);
@@ -982,18 +1022,19 @@ describe('RewardsNavigator', () => {
9821022
});
9831023

9841024
// Navigate away to a non-campaign route
985-
mockUseNavigationState.mockImplementation((selector) =>
986-
selector({
987-
routes: [
988-
{
989-
state: {
990-
routes: [{ name: Routes.REWARDS_DASHBOARD }],
991-
index: 0,
1025+
mockUseNavigationState.mockImplementation(
1026+
(selector: (state: unknown) => unknown) =>
1027+
selector({
1028+
routes: [
1029+
{
1030+
state: {
1031+
routes: [{ name: Routes.REWARDS_DASHBOARD }],
1032+
index: 0,
1033+
},
9921034
},
993-
},
994-
],
995-
index: 0,
996-
}),
1035+
],
1036+
index: 0,
1037+
}),
9971038
);
9981039

9991040
await act(async () => {
@@ -1003,6 +1044,136 @@ describe('RewardsNavigator', () => {
10031044
expect(mockCloseEnableNotificationsNudge).toHaveBeenCalledTimes(1);
10041045
});
10051046

1047+
it('does not show nudge again when session flag is already set', async () => {
1048+
mockUseRewardsNotificationsNudge.mockReturnValue({
1049+
areNotificationsEnabled: false,
1050+
canPromptToEnableNotifications: true,
1051+
shouldPromptToEnableNotifications: true,
1052+
showEnableNotificationsNudge: mockShowEnableNotificationsNudge,
1053+
closeEnableNotificationsNudge: mockCloseEnableNotificationsNudge,
1054+
runAfterNotificationsEnabled: jest.fn(),
1055+
});
1056+
mockUseNavigationState.mockImplementation(
1057+
(selector: (state: unknown) => unknown) =>
1058+
selector({
1059+
routes: [
1060+
{
1061+
state: {
1062+
routes: [{ name: Routes.REWARDS_CAMPAIGNS_VIEW }],
1063+
index: 0,
1064+
},
1065+
},
1066+
],
1067+
index: 0,
1068+
}),
1069+
);
1070+
1071+
renderWithNavigation(<RewardsNavigator />);
1072+
1073+
await waitFor(() => expect(true).toBe(true));
1074+
// sessionNotificationsNudgeShown was set true by the previous test
1075+
expect(mockShowEnableNotificationsNudge).not.toHaveBeenCalled();
1076+
});
1077+
1078+
it('evaluates route conditions for ONDO campaign route', async () => {
1079+
mockUseRewardsNotificationsNudge.mockReturnValue({
1080+
areNotificationsEnabled: false,
1081+
canPromptToEnableNotifications: true,
1082+
shouldPromptToEnableNotifications: true,
1083+
showEnableNotificationsNudge: mockShowEnableNotificationsNudge,
1084+
closeEnableNotificationsNudge: mockCloseEnableNotificationsNudge,
1085+
runAfterNotificationsEnabled: jest.fn(),
1086+
});
1087+
mockUseNavigationState.mockImplementation(
1088+
(selector: (state: unknown) => unknown) =>
1089+
selector({
1090+
routes: [
1091+
{
1092+
state: {
1093+
routes: [{ name: Routes.REWARDS_ONDO_CAMPAIGN_DETAILS_VIEW }],
1094+
index: 0,
1095+
},
1096+
},
1097+
],
1098+
index: 0,
1099+
}),
1100+
);
1101+
1102+
renderWithNavigation(<RewardsNavigator />);
1103+
1104+
await waitFor(() => expect(true).toBe(true));
1105+
// session flag already set — nudge not reshown, but route conditions were evaluated
1106+
expect(mockShowEnableNotificationsNudge).not.toHaveBeenCalled();
1107+
});
1108+
1109+
it('evaluates route conditions for SeasonOne campaign route', async () => {
1110+
mockUseRewardsNotificationsNudge.mockReturnValue({
1111+
areNotificationsEnabled: false,
1112+
canPromptToEnableNotifications: true,
1113+
shouldPromptToEnableNotifications: true,
1114+
showEnableNotificationsNudge: mockShowEnableNotificationsNudge,
1115+
closeEnableNotificationsNudge: mockCloseEnableNotificationsNudge,
1116+
runAfterNotificationsEnabled: jest.fn(),
1117+
});
1118+
mockUseNavigationState.mockImplementation(
1119+
(selector: (state: unknown) => unknown) =>
1120+
selector({
1121+
routes: [
1122+
{
1123+
state: {
1124+
routes: [
1125+
{
1126+
name: Routes.REWARDS_SEASON_ONE_CAMPAIGN_DETAILS_VIEW,
1127+
},
1128+
],
1129+
index: 0,
1130+
},
1131+
},
1132+
],
1133+
index: 0,
1134+
}),
1135+
);
1136+
1137+
renderWithNavigation(<RewardsNavigator />);
1138+
1139+
await waitFor(() => expect(true).toBe(true));
1140+
expect(mockShowEnableNotificationsNudge).not.toHaveBeenCalled();
1141+
});
1142+
1143+
it('evaluates route conditions for Perps Trading campaign route', async () => {
1144+
mockUseRewardsNotificationsNudge.mockReturnValue({
1145+
areNotificationsEnabled: false,
1146+
canPromptToEnableNotifications: true,
1147+
shouldPromptToEnableNotifications: true,
1148+
showEnableNotificationsNudge: mockShowEnableNotificationsNudge,
1149+
closeEnableNotificationsNudge: mockCloseEnableNotificationsNudge,
1150+
runAfterNotificationsEnabled: jest.fn(),
1151+
});
1152+
mockUseNavigationState.mockImplementation(
1153+
(selector: (state: unknown) => unknown) =>
1154+
selector({
1155+
routes: [
1156+
{
1157+
state: {
1158+
routes: [
1159+
{
1160+
name: Routes.REWARDS_PERPS_TRADING_CAMPAIGN_DETAILS_VIEW,
1161+
},
1162+
],
1163+
index: 0,
1164+
},
1165+
},
1166+
],
1167+
index: 0,
1168+
}),
1169+
);
1170+
1171+
renderWithNavigation(<RewardsNavigator />);
1172+
1173+
await waitFor(() => expect(true).toBe(true));
1174+
expect(mockShowEnableNotificationsNudge).not.toHaveBeenCalled();
1175+
});
1176+
10061177
it('calls success toast when onNotificationsEnabled callback fires', async () => {
10071178
let capturedCallback: (() => void) | undefined;
10081179
mockUseRewardsNotificationsNudge.mockImplementation(

app/components/UI/Rewards/components/Campaigns/CampaignTile.test.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ jest.mock('../../hooks/useRewardsToast', () => ({
8484
})),
8585
enableNotificationsNudge: mockEnableNotificationsNudge,
8686
entriesClosed: jest.fn(),
87+
loading: jest.fn((title: string, subtitle?: string) => ({
88+
variant: 'loading',
89+
title,
90+
subtitle,
91+
})),
8792
},
8893
})),
8994
}));

app/components/UI/Rewards/hooks/useLinkAccountAddress.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ describe('useLinkAccountAddress', () => {
8686
variant: 'plain',
8787
hapticsType: 'warning',
8888
}),
89+
loading: jest.fn().mockReturnValue({
90+
variant: 'loading',
91+
}),
8992
};
9093

9194
const mockAccount: InternalAccount = {

app/components/UI/Rewards/hooks/useLinkAccountGroup.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ describe('useLinkAccountGroup', () => {
107107
variant: 'plain',
108108
hapticsType: 'warning',
109109
}),
110+
loading: jest.fn().mockReturnValue({
111+
variant: 'loading',
112+
}),
110113
};
111114

112115
// Mock account data

0 commit comments

Comments
 (0)