Skip to content

Commit c40e334

Browse files
authored
Merge branch 'main' into NWNT-fix-tron-logo
2 parents 9c1f5be + e95cf72 commit c40e334

File tree

8 files changed

+96
-23
lines changed

8 files changed

+96
-23
lines changed
Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
import { renderHook, act } from '@testing-library/react-hooks';
22
// eslint-disable-next-line import/no-namespace
33
import * as PushNotificationsHooks from '../../../../util/notifications/hooks/usePushNotifications';
4+
// eslint-disable-next-line import/no-namespace
5+
import * as NotificationService from '../../../../util/notifications/services/NotificationService';
46
import { usePushNotificationSettingsToggle } from './PushNotificationToggle.hooks';
57

68
describe('usePushNotificationSettingsToggle', () => {
9+
beforeEach(() => jest.resetAllMocks());
10+
711
const arrange = () => {
812
const mockTogglePushNotification = jest.fn();
9-
13+
const mockGetPushPermission = jest.spyOn(
14+
NotificationService,
15+
'getPushPermission',
16+
);
17+
const mockOpenNotificationSettings = jest.spyOn(
18+
NotificationService.default,
19+
'openSystemSettings',
20+
);
1021
jest
1122
.spyOn(PushNotificationsHooks, 'usePushNotificationsToggle')
1223
.mockReturnValue({
@@ -17,16 +28,40 @@ describe('usePushNotificationSettingsToggle', () => {
1728

1829
const hook = renderHook(() => usePushNotificationSettingsToggle());
1930

20-
return { hook, mockTogglePushNotification };
31+
return {
32+
hook,
33+
mockTogglePushNotification,
34+
mockGetPushPermission,
35+
mockOpenNotificationSettings,
36+
};
2137
};
2238

2339
it('toggles the push notification setting', async () => {
24-
const { hook, mockTogglePushNotification } = arrange();
25-
40+
const { hook, mockTogglePushNotification, mockGetPushPermission } =
41+
arrange();
42+
mockGetPushPermission.mockResolvedValue('authorized');
2643
await act(async () => {
2744
hook.result.current.onToggle();
2845
});
2946

3047
expect(mockTogglePushNotification).toHaveBeenCalled();
3148
});
49+
50+
it('opens settings if permission is denied', async () => {
51+
const {
52+
hook,
53+
mockGetPushPermission,
54+
mockOpenNotificationSettings,
55+
mockTogglePushNotification,
56+
} = arrange();
57+
mockGetPushPermission.mockResolvedValue('denied');
58+
await act(async () => {
59+
hook.result.current.onToggle();
60+
});
61+
62+
// Assert - opens settings
63+
expect(mockOpenNotificationSettings).toHaveBeenCalled();
64+
// Assert - was not toggled as a user needs to complete settings action
65+
expect(mockTogglePushNotification).not.toHaveBeenCalled();
66+
});
3267
});

app/components/Views/Settings/NotificationsSettings/PushNotificationToggle.hooks.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
import { useCallback } from 'react';
2+
import NotificationService, {
3+
getPushPermission,
4+
} from '../../../../util/notifications/services/NotificationService';
25
import { usePushNotificationsToggle } from '../../../../util/notifications/hooks/usePushNotifications';
36

47
export function usePushNotificationSettingsToggle() {
58
const { data, togglePushNotification, loading } = usePushNotificationsToggle({
69
nudgeEnablePush: true,
710
});
8-
const onToggle = useCallback(
9-
() => togglePushNotification(!data),
10-
[data, togglePushNotification],
11-
);
11+
const onToggle = useCallback(async () => {
12+
const perm = await getPushPermission();
13+
if (perm === 'denied') {
14+
await NotificationService.openSystemSettings();
15+
return;
16+
}
17+
18+
togglePushNotification(!data);
19+
}, [data, togglePushNotification]);
1220
return {
1321
onToggle,
1422
value: data,

app/util/notifications/services/NotificationService.test.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
ChannelId,
1111
notificationChannels,
1212
} from '../../../util/notifications/androidChannels';
13-
import NotificationService from './NotificationService';
13+
import NotificationService, { getPushPermission } from './NotificationService';
1414
import { store } from '../../../store';
1515

1616
jest.mock('@notifee/react-native', () => ({
@@ -124,6 +124,28 @@ describe('NotificationsService - getBlockedNotifications', () => {
124124
});
125125
});
126126

127+
describe('getPushPermission', () => {
128+
const arrangeMocks = () => {
129+
const mockGetAllPermissions = jest.spyOn(
130+
NotificationService,
131+
'getAllPermissions',
132+
);
133+
return { mockGetAllPermissions };
134+
};
135+
136+
beforeEach(() => {
137+
jest.clearAllMocks();
138+
});
139+
140+
it('returns the push permission from getAllPermissions', async () => {
141+
const mocks = arrangeMocks();
142+
mocks.mockGetAllPermissions.mockResolvedValue({ permission: 'authorized' });
143+
expect(await getPushPermission()).toBe('authorized');
144+
mocks.mockGetAllPermissions.mockResolvedValue({ permission: 'denied' });
145+
expect(await getPushPermission()).toBe('denied');
146+
});
147+
});
148+
127149
describe('NotificationService - getAllPermissions', () => {
128150
const arrangeMocks = () => {
129151
const mockCreateChannel = jest

app/util/notifications/services/NotificationService.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,9 @@ class NotificationsService {
6060
}
6161
}
6262

63-
async getAllPermissions(shouldOpenSettings = true) {
63+
async getAllPermissions(
64+
shouldOpenSettings = true,
65+
): Promise<{ permission: 'authorized' | 'denied' }> {
6466
const promises: Promise<string>[] = notificationChannels.map(
6567
async (channel: AndroidChannel) =>
6668
await withTimeout(this.createChannel(channel), 5000),
@@ -174,10 +176,19 @@ class NotificationsService {
174176

175177
async hasPerimssion() {
176178
const settings = await notifee.getNotificationSettings();
177-
return settings.authorizationStatus === AuthorizationStatus.AUTHORIZED ||
178-
settings.authorizationStatus === AuthorizationStatus.PROVISIONAL
179-
? ('authorized' as const)
180-
: ('denied' as const);
179+
// status where we can assume authorized
180+
if (
181+
[
182+
AuthorizationStatus.NOT_DETERMINED,
183+
AuthorizationStatus.AUTHORIZED,
184+
AuthorizationStatus.PROVISIONAL,
185+
].includes(settings.authorizationStatus)
186+
) {
187+
return 'authorized' as const;
188+
}
189+
190+
// Otherwise this settings has been denied
191+
return 'denied' as const;
181192
}
182193

183194
onForegroundEvent = (
@@ -311,3 +322,8 @@ export async function hasPushPermission() {
311322
const result = await NotificationService.getAllPermissions(false);
312323
return result.permission === 'authorized';
313324
}
325+
326+
export async function getPushPermission() {
327+
const result = await NotificationService.getAllPermissions(false);
328+
return result.permission;
329+
}

app/util/notifications/settings/auth.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

app/util/notifications/settings/firebase.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
export * from './auth';
21
export * from './storage';
3-
export * from './firebase';

e2e/specs/predict/predict-cash-out.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ const PredictionMarketFeature = async (mockServer: Mockttp) => {
4444
};
4545

4646
describe(SmokePredictions('Predictions'), () => {
47-
it('should cash out on open position: Spurs vs. Pelicans', async () => {
47+
it.skip('should cash out on open position: Spurs vs. Pelicans', async () => {
4848
await withFixtures(
4949
{
5050
fixture: new FixtureBuilder().withPolygon().build(),

0 commit comments

Comments
 (0)