@imatis/react-native-notifications 4.1.2-imatis.7 → 4.2.4-imatis.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.buildkite/pipeline.yaml +39 -0
- package/.nvmrc +1 -0
- package/CHANGELOG.gren.md +384 -317
- package/CODEOWNERS +1 -1
- package/lib/android/.gradle/6.1.1/executionHistory/executionHistory.bin +0 -0
- package/lib/android/.gradle/6.1.1/executionHistory/executionHistory.lock +0 -0
- package/lib/android/.gradle/6.1.1/fileContent/fileContent.lock +0 -0
- package/lib/android/.gradle/6.1.1/fileHashes/fileHashes.bin +0 -0
- package/lib/android/.gradle/6.1.1/fileHashes/fileHashes.lock +0 -0
- package/lib/android/.gradle/6.1.1/fileHashes/resourceHashesCache.bin +0 -0
- package/lib/android/.gradle/6.1.1/javaCompile/classAnalysis.bin +0 -0
- package/lib/android/.gradle/6.1.1/javaCompile/jarAnalysis.bin +0 -0
- package/lib/android/.gradle/6.1.1/javaCompile/javaCompile.lock +0 -0
- package/lib/android/.gradle/6.1.1/javaCompile/taskHistory.bin +0 -0
- package/lib/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/lib/android/.gradle/buildOutputCleanup/cache.properties +1 -1
- package/lib/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
- package/lib/android/.gradle/checksums/checksums.lock +0 -0
- package/lib/android/.gradle/checksums/md5-checksums.bin +0 -0
- package/lib/android/.gradle/checksums/sha1-checksums.bin +0 -0
- package/lib/android/app/build.gradle +3 -5
- package/lib/android/app/src/main/AndroidManifest.xml +2 -1
- package/lib/android/app/src/main/java/com/wix/reactnativenotifications/RNNotificationsPackage.java +17 -14
- package/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/NotificationIntentAdapter.java +21 -7
- package/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotification.java +54 -24
- package/lib/android/app/src/main/java/com/wix/reactnativenotifications/core/notification/PushNotificationProps.java +24 -0
- package/lib/android/app/src/test/java/com/wix/reactnativenotifications/core/AppLaunchHelperTest.java +117 -0
- package/lib/android/app/src/test/java/com/wix/reactnativenotifications/core/InitialNotificationHolderTest.java +59 -0
- package/lib/android/app/src/test/java/com/wix/reactnativenotifications/core/JsIOHelperTest.java +60 -0
- package/lib/android/app/src/test/java/com/wix/reactnativenotifications/core/notification/PushNotificationTest.java +381 -0
- package/lib/android/app/src/test/java/com/wix/reactnativenotifications/core/notificationdrawer/PushNotificationsDrawerTest.java +96 -0
- package/lib/android/app/src/test/resources/robolectric.properties +1 -0
- package/lib/android/build.gradle +1 -1
- package/lib/android/local.properties +2 -2
- package/lib/dist/commands/Commands.test.js +2 -0
- package/lib/dist/interfaces/NotificationCategory.d.ts +3 -2
- package/lib/dist/interfaces/NotificationPermissions.d.ts +2 -0
- package/lib/src/interfaces/NotificationCategory.ts +4 -2
- package/metro.config.js +0 -1
- package/package.json +10 -13
- package/react-native-notifications.podspec +6 -5
- package/react-native.config.js +8 -0
- package/android/app/src/reactNative59/reactNative59.iml +0 -11
- package/android/app/src/reactNative60/reactNative60.iml +0 -11
- package/lib/ios/RNNotifications.xcodeproj/project.xcworkspace/xcuserdata/troy.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/package-lock.json +0 -13507
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
package com.wix.reactnativenotifications.core.notification;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.app.Notification;
|
|
5
|
+
import android.app.NotificationChannel;
|
|
6
|
+
import android.app.NotificationManager;
|
|
7
|
+
import android.content.Context;
|
|
8
|
+
import android.content.Intent;
|
|
9
|
+
import android.content.pm.ApplicationInfo;
|
|
10
|
+
import android.content.pm.PackageManager;
|
|
11
|
+
import android.content.res.Resources;
|
|
12
|
+
import android.os.Bundle;
|
|
13
|
+
import android.os.Message;
|
|
14
|
+
|
|
15
|
+
import com.facebook.react.bridge.Arguments;
|
|
16
|
+
import com.facebook.react.bridge.JavaOnlyMap;
|
|
17
|
+
import com.facebook.react.bridge.ReactContext;
|
|
18
|
+
import com.facebook.react.bridge.WritableMap;
|
|
19
|
+
import com.wix.reactnativenotifications.core.AppLaunchHelper;
|
|
20
|
+
import com.wix.reactnativenotifications.core.AppLifecycleFacade;
|
|
21
|
+
import com.wix.reactnativenotifications.core.AppLifecycleFacade.AppVisibilityListener;
|
|
22
|
+
import com.wix.reactnativenotifications.core.InitialNotificationHolder;
|
|
23
|
+
import com.wix.reactnativenotifications.core.JsIOHelper;
|
|
24
|
+
|
|
25
|
+
import org.junit.Before;
|
|
26
|
+
import org.junit.Test;
|
|
27
|
+
import org.junit.runner.RunWith;
|
|
28
|
+
import org.mockito.ArgumentCaptor;
|
|
29
|
+
import org.mockito.ArgumentMatcher;
|
|
30
|
+
import org.mockito.Mock;
|
|
31
|
+
import org.mockito.MockitoAnnotations;
|
|
32
|
+
import org.robolectric.RobolectricTestRunner;
|
|
33
|
+
import org.robolectric.Shadows;
|
|
34
|
+
import org.robolectric.shadows.ShadowNotification;
|
|
35
|
+
|
|
36
|
+
import static org.junit.Assert.assertEquals;
|
|
37
|
+
import static org.junit.Assert.assertNotEquals;
|
|
38
|
+
import static org.mockito.ArgumentMatchers.any;
|
|
39
|
+
import static org.mockito.ArgumentMatchers.anyInt;
|
|
40
|
+
import static org.mockito.ArgumentMatchers.eq;
|
|
41
|
+
import static org.mockito.Mockito.mock;
|
|
42
|
+
import static org.mockito.Mockito.never;
|
|
43
|
+
import static org.mockito.Mockito.times;
|
|
44
|
+
import static org.mockito.Mockito.verify;
|
|
45
|
+
import static org.mockito.Mockito.when;
|
|
46
|
+
import static org.mockito.Mockito.argThat;
|
|
47
|
+
|
|
48
|
+
import java.util.ArrayList;
|
|
49
|
+
import java.util.List;
|
|
50
|
+
|
|
51
|
+
import edu.emory.mathcs.backport.java.util.Arrays;
|
|
52
|
+
|
|
53
|
+
@RunWith(RobolectricTestRunner.class)
|
|
54
|
+
public class PushNotificationTest {
|
|
55
|
+
|
|
56
|
+
private static final String NOTIFICATION_OPENED_EVENT_NAME = "notificationOpened";
|
|
57
|
+
private static final String NOTIFICATION_RECEIVED_EVENT_NAME = "notificationReceived";
|
|
58
|
+
private static final String NOTIFICATION_RECEIVED_BACKGROUND_EVENT_NAME = "notificationReceivedBackground";
|
|
59
|
+
|
|
60
|
+
private static final String DEFAULT_NOTIFICATION_TITLE = "Notification-title";
|
|
61
|
+
private static final String DEFAULT_NOTIFICATION_BODY = "Notification-body";
|
|
62
|
+
|
|
63
|
+
@Mock private ReactContext mReactContext;
|
|
64
|
+
@Mock private Context mContext;
|
|
65
|
+
@Mock private NotificationManager mNotificationManager;
|
|
66
|
+
|
|
67
|
+
private Bundle mResponseBundle;
|
|
68
|
+
private Bundle mNotificationBundle;
|
|
69
|
+
@Mock private Intent mLaunchIntent;
|
|
70
|
+
@Mock private AppLifecycleFacade mAppLifecycleFacade;
|
|
71
|
+
@Mock private AppLaunchHelper mAppLaunchHelper;
|
|
72
|
+
@Mock private JsIOHelper mJsIOHelper;
|
|
73
|
+
@Mock private Resources mResources;
|
|
74
|
+
@Mock private PackageManager mPackageManager;
|
|
75
|
+
|
|
76
|
+
@Before
|
|
77
|
+
public void setup() throws Exception {
|
|
78
|
+
MockitoAnnotations.initMocks(this);
|
|
79
|
+
InitialNotificationHolder.setInstance(mock(InitialNotificationHolder.class));
|
|
80
|
+
|
|
81
|
+
mNotificationBundle = new Bundle();
|
|
82
|
+
mNotificationBundle.putString("title", DEFAULT_NOTIFICATION_TITLE);
|
|
83
|
+
mNotificationBundle.putString("body", DEFAULT_NOTIFICATION_BODY);
|
|
84
|
+
|
|
85
|
+
mResponseBundle = new Bundle();
|
|
86
|
+
mResponseBundle.putBundle("notification", mNotificationBundle);
|
|
87
|
+
|
|
88
|
+
when(mAppLaunchHelper.getLaunchIntent(eq(mContext))).thenReturn(mLaunchIntent);
|
|
89
|
+
|
|
90
|
+
ApplicationInfo ai = mock(ApplicationInfo.class);
|
|
91
|
+
when(mContext.getApplicationInfo()).thenReturn(ai);
|
|
92
|
+
when(mContext.getResources()).thenReturn(mResources);
|
|
93
|
+
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
|
94
|
+
when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(mNotificationManager);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@Test
|
|
98
|
+
public void onOpened_noReactContext_launchApp() throws Exception {
|
|
99
|
+
when(mAppLifecycleFacade.isReactInitialized()).thenReturn(false);
|
|
100
|
+
|
|
101
|
+
final PushNotification uut = createUUT();
|
|
102
|
+
uut.onOpened();
|
|
103
|
+
|
|
104
|
+
verify(mContext).startActivity(eq(mLaunchIntent));
|
|
105
|
+
|
|
106
|
+
// The unit shouldn't wait for visibility in this case cause we dont make the extra effort of
|
|
107
|
+
// notifying the notification upon app launch completion (simply cause we dont know when in completes).
|
|
108
|
+
// Instead, the user is expected to use getInitialNotification().
|
|
109
|
+
verify(mAppLifecycleFacade, never()).addVisibilityListener(any(AppVisibilityListener.class));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
@Test
|
|
113
|
+
public void onOpened_noReactContext_setAsInitialNotification() throws Exception {
|
|
114
|
+
when(mAppLifecycleFacade.isReactInitialized()).thenReturn(false);
|
|
115
|
+
Activity currentActivity = mock(Activity.class);
|
|
116
|
+
when(mReactContext.getCurrentActivity()).thenReturn(currentActivity);
|
|
117
|
+
|
|
118
|
+
final PushNotification uut = createUUT();
|
|
119
|
+
uut.onOpened();
|
|
120
|
+
|
|
121
|
+
verify(InitialNotificationHolder.getInstance()).set(any(PushNotificationProps.class));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@Test
|
|
125
|
+
public void onOpened_appInvisible_resumeAppWaitForVisibility() throws Exception {
|
|
126
|
+
setUpBackgroundApp();
|
|
127
|
+
|
|
128
|
+
final PushNotification uut = createUUT();
|
|
129
|
+
uut.onOpened();
|
|
130
|
+
|
|
131
|
+
verify(mContext).startActivity(any(Intent.class));
|
|
132
|
+
verify(mAppLifecycleFacade).addVisibilityListener(any(AppVisibilityListener.class));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@Test
|
|
136
|
+
public void onOpened_appInvisible_dontSetInitialNotification() throws Exception {
|
|
137
|
+
setUpBackgroundApp();
|
|
138
|
+
Activity currentActivity = mock(Activity.class);
|
|
139
|
+
when(mReactContext.getCurrentActivity()).thenReturn(currentActivity);
|
|
140
|
+
|
|
141
|
+
final PushNotification uut = createUUT();
|
|
142
|
+
uut.onOpened();
|
|
143
|
+
|
|
144
|
+
verify(InitialNotificationHolder.getInstance(), never()).set(any(PushNotificationProps.class));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@Test
|
|
148
|
+
public void onOpened_appGoesVisible_resumeAppAndNotifyJs() throws Exception {
|
|
149
|
+
|
|
150
|
+
// Arrange
|
|
151
|
+
|
|
152
|
+
setUpBackgroundApp();
|
|
153
|
+
|
|
154
|
+
// Act
|
|
155
|
+
|
|
156
|
+
final PushNotification uut = createUUT();
|
|
157
|
+
uut.onOpened();
|
|
158
|
+
|
|
159
|
+
// Hijack and invoke visibility listener
|
|
160
|
+
ArgumentCaptor<AppVisibilityListener> listenerCaptor = ArgumentCaptor.forClass(AppVisibilityListener.class);
|
|
161
|
+
verify(mAppLifecycleFacade).addVisibilityListener(listenerCaptor.capture());
|
|
162
|
+
AppVisibilityListener listener = listenerCaptor.getValue();
|
|
163
|
+
listener.onAppVisible();
|
|
164
|
+
|
|
165
|
+
// Assert
|
|
166
|
+
|
|
167
|
+
verify(mJsIOHelper).sendEventToJS(eq(NOTIFICATION_OPENED_EVENT_NAME), argThat(new isValidResponse(mResponseBundle)), eq(mReactContext));
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
@Test
|
|
171
|
+
public void onOpened_appVisible_notifyJS() throws Exception {
|
|
172
|
+
setUpForegroundApp();
|
|
173
|
+
|
|
174
|
+
final PushNotification uut = createUUT();
|
|
175
|
+
uut.onOpened();
|
|
176
|
+
|
|
177
|
+
verify(mContext, never()).startActivity(any(Intent.class));
|
|
178
|
+
verify(mJsIOHelper).sendEventToJS(eq(NOTIFICATION_OPENED_EVENT_NAME), argThat(new isValidResponse(mResponseBundle)), eq(mReactContext));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
@Test
|
|
182
|
+
public void onOpened_appVisible_clearNotificationsDrawer() throws Exception {
|
|
183
|
+
verify(mNotificationManager, never()).cancelAll();
|
|
184
|
+
setUpForegroundApp();
|
|
185
|
+
|
|
186
|
+
final PushNotification uut = createUUT();
|
|
187
|
+
uut.onOpened();
|
|
188
|
+
|
|
189
|
+
verify(mNotificationManager, never()).cancelAll();
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
@Test
|
|
193
|
+
public void onOpened_appVisible_dontSetInitialNotification() throws Exception {
|
|
194
|
+
setUpForegroundApp();
|
|
195
|
+
Activity currentActivity = mock(Activity.class);
|
|
196
|
+
when(mReactContext.getCurrentActivity()).thenReturn(currentActivity);
|
|
197
|
+
|
|
198
|
+
final PushNotification uut = createUUT();
|
|
199
|
+
uut.onOpened();
|
|
200
|
+
|
|
201
|
+
verify(InitialNotificationHolder.getInstance(), never()).set(any(PushNotificationProps.class));
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@Test
|
|
205
|
+
public void onOpened_reactInitializedWithNoActivities_setAsInitialNotification() throws Exception {
|
|
206
|
+
setUpBackgroundApp();
|
|
207
|
+
when(mReactContext.getCurrentActivity()).thenReturn(null); // Just for clarity
|
|
208
|
+
|
|
209
|
+
final PushNotification uut = createUUT();
|
|
210
|
+
uut.onOpened();
|
|
211
|
+
|
|
212
|
+
verify(InitialNotificationHolder.getInstance()).set(any(PushNotificationProps.class));
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@Test
|
|
216
|
+
public void onReceived_validData_dontPostNotificationAndNotifyJS() throws Exception {
|
|
217
|
+
// Arrange
|
|
218
|
+
|
|
219
|
+
setUpForegroundApp();
|
|
220
|
+
|
|
221
|
+
// Act
|
|
222
|
+
|
|
223
|
+
final PushNotification uut = createUUT();
|
|
224
|
+
uut.onReceived();
|
|
225
|
+
|
|
226
|
+
// Assert
|
|
227
|
+
|
|
228
|
+
ArgumentCaptor<Notification> notificationCaptor = ArgumentCaptor.forClass(Notification.class);
|
|
229
|
+
verify(mNotificationManager, never()).notify(anyInt(), notificationCaptor.capture());
|
|
230
|
+
verify(mJsIOHelper).sendEventToJS(eq(NOTIFICATION_RECEIVED_EVENT_NAME), argThat(new isValidNotification(mNotificationBundle)), eq(mReactContext));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@Test
|
|
234
|
+
public void onReceived_validDataForBackgroundApp_postNotificationAndNotifyJs() throws Exception {
|
|
235
|
+
// Arrange
|
|
236
|
+
|
|
237
|
+
setUpBackgroundApp();
|
|
238
|
+
|
|
239
|
+
// Act
|
|
240
|
+
|
|
241
|
+
final PushNotification uut = createUUT();
|
|
242
|
+
uut.onReceived();
|
|
243
|
+
|
|
244
|
+
// Assert
|
|
245
|
+
|
|
246
|
+
ArgumentCaptor<Notification> notificationCaptor = ArgumentCaptor.forClass(Notification.class);
|
|
247
|
+
verify(mNotificationManager).notify(anyInt(), notificationCaptor.capture());
|
|
248
|
+
verify(mJsIOHelper).sendEventToJS(eq(NOTIFICATION_RECEIVED_BACKGROUND_EVENT_NAME), argThat(new isValidNotification(mNotificationBundle)), eq(mReactContext));
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
@Test
|
|
252
|
+
public void onReceived_validDataForDeadApp_postNotificationDontNotifyJS() throws Exception {
|
|
253
|
+
final PushNotification uut = createUUT();
|
|
254
|
+
uut.onReceived();
|
|
255
|
+
|
|
256
|
+
ArgumentCaptor<Notification> notificationCaptor = ArgumentCaptor.forClass(Notification.class);
|
|
257
|
+
verify(mNotificationManager).notify(anyInt(), notificationCaptor.capture());
|
|
258
|
+
verifyNotification(notificationCaptor.getValue());
|
|
259
|
+
verify(mJsIOHelper).sendEventToJS(eq(NOTIFICATION_RECEIVED_BACKGROUND_EVENT_NAME), argThat(new isValidNotification(mNotificationBundle)), eq(null));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@Test
|
|
263
|
+
public void onPostRequest_withValidDataButNoId_postNotifications() throws Exception {
|
|
264
|
+
|
|
265
|
+
// Arrange
|
|
266
|
+
|
|
267
|
+
setUpForegroundApp();
|
|
268
|
+
|
|
269
|
+
// Act
|
|
270
|
+
|
|
271
|
+
final PushNotification uut = createUUT();
|
|
272
|
+
uut.onPostRequest(null);
|
|
273
|
+
|
|
274
|
+
// Assert
|
|
275
|
+
|
|
276
|
+
ArgumentCaptor<Notification> notificationCaptor = ArgumentCaptor.forClass(Notification.class);
|
|
277
|
+
verify(mNotificationManager).notify(anyInt(), notificationCaptor.capture());
|
|
278
|
+
verifyNotification(notificationCaptor.getValue());
|
|
279
|
+
|
|
280
|
+
// Shouldn't notify an event on an explicit call to notification posting
|
|
281
|
+
verify(mJsIOHelper, never()).sendEventToJS(eq(NOTIFICATION_RECEIVED_EVENT_NAME), any(Bundle.class), any(ReactContext.class));
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
@Test
|
|
285
|
+
public void onPostRequest_withValidDataButNoId_idsShouldBeUnique() throws Exception {
|
|
286
|
+
createUUT().onPostRequest(null);
|
|
287
|
+
createUUT().onPostRequest(null);
|
|
288
|
+
|
|
289
|
+
ArgumentCaptor<Integer> idsCaptor = ArgumentCaptor.forClass(Integer.class);
|
|
290
|
+
verify(mNotificationManager, times(2)).notify(idsCaptor.capture(), any(Notification.class));
|
|
291
|
+
assertNotEquals(idsCaptor.getAllValues().get(0), idsCaptor.getAllValues().get(1));
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
@Test
|
|
295
|
+
public void onPostRequest_withValidDataAndExplicitId_postNotification() throws Exception {
|
|
296
|
+
final int id = 666;
|
|
297
|
+
|
|
298
|
+
final PushNotification uut = createUUT();
|
|
299
|
+
uut.onPostRequest(id);
|
|
300
|
+
|
|
301
|
+
verify(mNotificationManager).notify(eq(id), any(Notification.class));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
@Test
|
|
305
|
+
public void onPostRequest_emptyData_postNotification() throws Exception {
|
|
306
|
+
PushNotification uut = createUUT(new Bundle());
|
|
307
|
+
uut.onPostRequest(null);
|
|
308
|
+
|
|
309
|
+
verify(mNotificationManager, never()).notify(anyInt(), any(Notification.class));
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
@Test
|
|
313
|
+
public void onCreate_noExistingChannel_createDefaultChannel() throws Exception {
|
|
314
|
+
createUUT();
|
|
315
|
+
|
|
316
|
+
verify(mNotificationManager).createNotificationChannel(any(NotificationChannel.class));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
@Test
|
|
320
|
+
public void onCreate_existingChannel_notCreateDefaultChannel() throws Exception {
|
|
321
|
+
List<NotificationChannel> existingChannel = new ArrayList<>();
|
|
322
|
+
existingChannel.add(new NotificationChannel("id", "name", 1));
|
|
323
|
+
when(mNotificationManager.getNotificationChannels()).thenReturn(existingChannel);
|
|
324
|
+
|
|
325
|
+
createUUT();
|
|
326
|
+
|
|
327
|
+
verify(mNotificationManager, never()).createNotificationChannel(any(NotificationChannel.class));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
protected PushNotification createUUT() {
|
|
331
|
+
return createUUT(mNotificationBundle);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
protected PushNotification createUUT(Bundle bundle) {
|
|
335
|
+
return new PushNotification(mContext, bundle, mAppLifecycleFacade, mAppLaunchHelper, mJsIOHelper);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
protected void setUpBackgroundApp() {
|
|
339
|
+
when(mAppLifecycleFacade.isReactInitialized()).thenReturn(true);
|
|
340
|
+
when(mAppLifecycleFacade.getRunningReactContext()).thenReturn(mReactContext);
|
|
341
|
+
when(mAppLifecycleFacade.isAppVisible()).thenReturn(false);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
protected void setUpForegroundApp() {
|
|
345
|
+
when(mAppLifecycleFacade.isReactInitialized()).thenReturn(true);
|
|
346
|
+
when(mAppLifecycleFacade.getRunningReactContext()).thenReturn(mReactContext);
|
|
347
|
+
when(mAppLifecycleFacade.isAppVisible()).thenReturn(true);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
protected void verifyNotification(Notification notification) {
|
|
351
|
+
ShadowNotification shadowNotification = Shadows.shadowOf(notification);
|
|
352
|
+
assertEquals(shadowNotification.getContentText(), DEFAULT_NOTIFICATION_BODY);
|
|
353
|
+
assertEquals(shadowNotification.getContentTitle(), DEFAULT_NOTIFICATION_TITLE);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private class isValidNotification implements ArgumentMatcher<Bundle> {
|
|
357
|
+
private Bundle left;
|
|
358
|
+
|
|
359
|
+
protected isValidNotification(Bundle left) {
|
|
360
|
+
this.left = left;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
@Override
|
|
364
|
+
public boolean matches(Bundle right) {
|
|
365
|
+
return right.getString("body").equals(left.getString("body"));
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
private class isValidResponse implements ArgumentMatcher<Bundle> {
|
|
370
|
+
private Bundle left;
|
|
371
|
+
|
|
372
|
+
protected isValidResponse(Bundle left) {
|
|
373
|
+
this.left = left;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
@Override
|
|
377
|
+
public boolean matches(Bundle right) {
|
|
378
|
+
return right.getBundle("notification").getString("body").equals(left.getBundle("notification").getString("body"));
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
package com.wix.reactnativenotifications.core.notificationdrawer;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.app.NotificationManager;
|
|
5
|
+
import android.content.Context;
|
|
6
|
+
import android.content.Intent;
|
|
7
|
+
|
|
8
|
+
import com.facebook.react.bridge.ReactContext;
|
|
9
|
+
import com.wix.reactnativenotifications.core.AppLaunchHelper;
|
|
10
|
+
import com.wix.reactnativenotifications.core.InitialNotificationHolder;
|
|
11
|
+
|
|
12
|
+
import org.junit.Before;
|
|
13
|
+
import org.junit.Test;
|
|
14
|
+
import org.junit.runner.RunWith;
|
|
15
|
+
import org.mockito.Mock;
|
|
16
|
+
import org.mockito.MockitoAnnotations;
|
|
17
|
+
import org.robolectric.RobolectricTestRunner;
|
|
18
|
+
|
|
19
|
+
import static org.mockito.ArgumentMatchers.any;
|
|
20
|
+
import static org.mockito.ArgumentMatchers.eq;
|
|
21
|
+
import static org.mockito.Mockito.mock;
|
|
22
|
+
import static org.mockito.Mockito.never;
|
|
23
|
+
import static org.mockito.Mockito.verify;
|
|
24
|
+
import static org.mockito.Mockito.when;
|
|
25
|
+
|
|
26
|
+
@RunWith(RobolectricTestRunner.class)
|
|
27
|
+
public class PushNotificationsDrawerTest {
|
|
28
|
+
|
|
29
|
+
@Mock private ReactContext mReactContext;
|
|
30
|
+
@Mock private Context mContext;
|
|
31
|
+
@Mock private NotificationManager mNotificationManager;
|
|
32
|
+
@Mock private AppLaunchHelper mAppLaunchHelper;
|
|
33
|
+
|
|
34
|
+
@Before
|
|
35
|
+
public void setup() throws Exception {
|
|
36
|
+
MockitoAnnotations.initMocks(this);
|
|
37
|
+
|
|
38
|
+
InitialNotificationHolder.setInstance(mock(InitialNotificationHolder.class));
|
|
39
|
+
when(mContext.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(mNotificationManager);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@Test
|
|
43
|
+
public void onAppInit_neverClearAllNotifications() throws Exception {
|
|
44
|
+
createUUT().onAppInit();
|
|
45
|
+
verify(mNotificationManager, never()).cancelAll();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Test
|
|
49
|
+
public void onAppVisible_neverClearAllNotifications() throws Exception {
|
|
50
|
+
createUUT().onAppVisible();
|
|
51
|
+
verify(mNotificationManager, never()).cancelAll();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@Test
|
|
55
|
+
public void onNotificationOpened_neverClearAllNotifications() throws Exception {
|
|
56
|
+
createUUT().onNotificationOpened();
|
|
57
|
+
verify(mNotificationManager, never()).cancelAll();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Test
|
|
61
|
+
public void onNotificationClearRequest_clearSpecificNotification() throws Exception {
|
|
62
|
+
createUUT().onNotificationClearRequest(666);
|
|
63
|
+
verify(mNotificationManager).cancel(eq(666));
|
|
64
|
+
verify(mNotificationManager, never()).cancelAll();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@Test
|
|
68
|
+
public void onNewActivity_activityIsNotTheOneLaunchedByNotifs_dontClearInitialNotification() throws Exception {
|
|
69
|
+
Activity activity = mock(Activity.class);
|
|
70
|
+
Intent intent = mock(Intent.class);
|
|
71
|
+
when(activity.getIntent()).thenReturn(intent);
|
|
72
|
+
when(mAppLaunchHelper.isLaunchIntentsActivity(activity)).thenReturn(false);
|
|
73
|
+
when(mAppLaunchHelper.isLaunchIntentOfNotification(any(Intent.class))).thenReturn(false);
|
|
74
|
+
|
|
75
|
+
createUUT().onNewActivity(activity);
|
|
76
|
+
|
|
77
|
+
verify(InitialNotificationHolder.getInstance(), never()).clear();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@Test
|
|
81
|
+
public void onNewActivity_activityLaunchedFromPushNotification_dontClearInitialNotification() throws Exception {
|
|
82
|
+
Activity activity = mock(Activity.class);
|
|
83
|
+
Intent intent = mock(Intent.class);
|
|
84
|
+
when(activity.getIntent()).thenReturn(intent);
|
|
85
|
+
when(mAppLaunchHelper.isLaunchIntentsActivity(activity)).thenReturn(true);
|
|
86
|
+
when(mAppLaunchHelper.isLaunchIntentOfNotification(eq(intent))).thenReturn(true);
|
|
87
|
+
|
|
88
|
+
createUUT().onNewActivity(activity);
|
|
89
|
+
|
|
90
|
+
verify(InitialNotificationHolder.getInstance(), never()).clear();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
protected PushNotificationsDrawer createUUT() {
|
|
94
|
+
return new PushNotificationsDrawer(mContext, mAppLaunchHelper);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
sdk=28
|
package/lib/android/build.gradle
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
# Location of the SDK. This is only used by Gradle.
|
|
5
5
|
# For customization when using a Version Control System, please read the
|
|
6
6
|
# header note.
|
|
7
|
-
#
|
|
8
|
-
sdk.dir=/Users/
|
|
7
|
+
#Tue Mar 22 09:43:01 CET 2022
|
|
8
|
+
sdk.dir=/Users/larserlingdahl/Library/Android/sdk
|
|
@@ -165,6 +165,8 @@ describe('Commands', () => {
|
|
|
165
165
|
providesAppNotificationSettings: false,
|
|
166
166
|
provisional: false,
|
|
167
167
|
announcement: false,
|
|
168
|
+
notificationCenter: true,
|
|
169
|
+
lockScreen: false,
|
|
168
170
|
};
|
|
169
171
|
ts_mockito_1.when(mockedNativeCommandsSender.checkPermissions()).thenResolve(expectedPermissions);
|
|
170
172
|
const permissions = await uut.checkPermissions();
|
|
@@ -7,11 +7,12 @@ export interface NotificationTextInput {
|
|
|
7
7
|
buttonTitle: string;
|
|
8
8
|
placeholder: string;
|
|
9
9
|
}
|
|
10
|
+
export declare type ActivationMode = 'background' | 'foreground' | 'authenticationRequired' | 'destructive';
|
|
10
11
|
export declare class NotificationAction {
|
|
11
12
|
identifier: string;
|
|
12
|
-
activationMode:
|
|
13
|
+
activationMode: ActivationMode;
|
|
13
14
|
title: string;
|
|
14
15
|
authenticationRequired: boolean;
|
|
15
16
|
textInput?: NotificationTextInput;
|
|
16
|
-
constructor(identifier: string, activationMode:
|
|
17
|
+
constructor(identifier: string, activationMode: ActivationMode, title: string, authenticationRequired: boolean, textInput?: NotificationTextInput);
|
|
17
18
|
}
|
|
@@ -13,14 +13,16 @@ export interface NotificationTextInput {
|
|
|
13
13
|
placeholder: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
+
export type ActivationMode = 'background' | 'foreground' | 'authenticationRequired' | 'destructive';
|
|
17
|
+
|
|
16
18
|
export class NotificationAction {
|
|
17
19
|
identifier: string;
|
|
18
|
-
activationMode:
|
|
20
|
+
activationMode: ActivationMode;
|
|
19
21
|
title: string;
|
|
20
22
|
authenticationRequired: boolean;
|
|
21
23
|
textInput?: NotificationTextInput;
|
|
22
24
|
|
|
23
|
-
constructor(identifier: string, activationMode:
|
|
25
|
+
constructor(identifier: string, activationMode: ActivationMode, title: string, authenticationRequired: boolean, textInput?: NotificationTextInput) {
|
|
24
26
|
this.identifier = identifier;
|
|
25
27
|
this.activationMode = activationMode;
|
|
26
28
|
this.title = title;
|
package/metro.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@imatis/react-native-notifications",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.2.4-imatis.21",
|
|
4
4
|
"description": "Advanced Push Notifications (Silent, interactive notifications) for iOS & Android",
|
|
5
|
-
"author": "Lidan Hifi <lidan.hifi@gmail.com>",
|
|
6
5
|
"license": "MIT",
|
|
7
6
|
"keywords": [
|
|
8
7
|
"react-component",
|
|
@@ -37,7 +36,7 @@
|
|
|
37
36
|
"test-unit-android": "node ./scripts/test-unit --android",
|
|
38
37
|
"test-js": "node ./scripts/test-js",
|
|
39
38
|
"xcode": "open example/ios/NotificationsExampleApp.xcworkspace",
|
|
40
|
-
"
|
|
39
|
+
"studio": "open -a /Applications/Android\\ Studio.app ./example/android",
|
|
41
40
|
"prerelease": "npm run build",
|
|
42
41
|
"release": "node ./scripts/release",
|
|
43
42
|
"generate-changelog": "gren changelog",
|
|
@@ -46,8 +45,8 @@
|
|
|
46
45
|
},
|
|
47
46
|
"nativePackage": true,
|
|
48
47
|
"peerDependencies": {
|
|
49
|
-
"react": "
|
|
50
|
-
"react-native": "
|
|
48
|
+
"react": "*",
|
|
49
|
+
"react-native": "*"
|
|
51
50
|
},
|
|
52
51
|
"devDependencies": {
|
|
53
52
|
"@babel/plugin-proposal-export-default-from": "7.2.0",
|
|
@@ -55,19 +54,17 @@
|
|
|
55
54
|
"@types/jest": "24.9.0",
|
|
56
55
|
"@types/lodash": "4.14.170",
|
|
57
56
|
"@types/react": "16.9.35",
|
|
58
|
-
"@types/react-native": "0.
|
|
57
|
+
"@types/react-native": "0.67.1",
|
|
59
58
|
"@types/react-test-renderer": "16.9.2",
|
|
60
59
|
"babel-eslint": "10.0.3",
|
|
61
|
-
"detox": "^
|
|
60
|
+
"detox": "^19.4.2",
|
|
62
61
|
"github-release-notes": "https://github.com/yogevbd/github-release-notes/tarball/e601b3dba72dcd6cba323c1286ea6dd0c0110b58",
|
|
63
|
-
"hermes-engine": "0.4.2-rc1",
|
|
64
62
|
"jest": "24.9.0",
|
|
65
63
|
"lodash": "4.17.21",
|
|
66
|
-
"metro-react-native-babel-preset": "0.
|
|
67
|
-
"react": "
|
|
64
|
+
"metro-react-native-babel-preset": "0.66.2",
|
|
65
|
+
"react": "17.0.2",
|
|
68
66
|
"react-autobind": "1.0.6",
|
|
69
|
-
"react-native": "0.
|
|
70
|
-
"react-native-typescript-transformer": "1.2.13",
|
|
67
|
+
"react-native": "0.67.3",
|
|
71
68
|
"shell-utils": "1.0.10",
|
|
72
69
|
"ts-mockito": "2.5.0",
|
|
73
70
|
"tslint": "6.1.2",
|
|
@@ -134,4 +131,4 @@
|
|
|
134
131
|
"html"
|
|
135
132
|
]
|
|
136
133
|
}
|
|
137
|
-
}
|
|
134
|
+
}
|
|
@@ -6,15 +6,16 @@ Pod::Spec.new do |s|
|
|
|
6
6
|
s.name = 'react-native-notifications'
|
|
7
7
|
s.version = package['version']
|
|
8
8
|
s.summary = package['description']
|
|
9
|
-
|
|
10
|
-
s.
|
|
11
|
-
s.author = package['author']
|
|
9
|
+
|
|
10
|
+
s.authors = "Wix.com"
|
|
12
11
|
s.homepage = package['homepage']
|
|
12
|
+
s.license = package['license']
|
|
13
|
+
s.platform = :ios, '11.0'
|
|
14
|
+
|
|
15
|
+
s.module_name = 'RNNotifications'
|
|
13
16
|
s.source = { :git => 'https://github.com/wix/react-native-notifications', :tag => s.version }
|
|
14
|
-
s.module_name = 'RNNotifications'
|
|
15
17
|
|
|
16
18
|
s.requires_arc = true
|
|
17
|
-
s.platform = :ios, '8.0'
|
|
18
19
|
|
|
19
20
|
s.preserve_paths = 'LICENSE', 'README.md', 'package.json', 'notification.ios.js', 'notification.android.js', 'index.android.js', 'index.ios.js'
|
|
20
21
|
s.source_files = 'lib/ios/*.{h,m}'
|
package/react-native.config.js
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<module type="JAVA_MODULE" version="4">
|
|
3
|
-
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
|
4
|
-
<exclude-output />
|
|
5
|
-
<content url="file://$MODULE_DIR$">
|
|
6
|
-
<sourceFolder url="file://$MODULE_DIR$/java" isTestSource="false" />
|
|
7
|
-
</content>
|
|
8
|
-
<orderEntry type="inheritedJdk" />
|
|
9
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
|
10
|
-
</component>
|
|
11
|
-
</module>
|