react-native-notify-kit 10.2.1 → 10.3.0

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.
Files changed (42) hide show
  1. package/android/src/main/java/app/notifee/core/ForegroundService.java +3 -1
  2. package/android/src/main/java/app/notifee/core/NotifeeAlarmManager.java +4 -2
  3. package/android/src/main/java/app/notifee/core/NotificationManager.java +28 -35
  4. package/android/src/main/java/app/notifee/core/database/NotifeeCoreDatabase.java +1 -4
  5. package/android/src/main/java/app/notifee/core/model/ChannelModel.java +8 -13
  6. package/android/src/main/java/app/notifee/core/model/IntervalTriggerModel.java +2 -6
  7. package/android/src/main/java/app/notifee/core/model/NotificationAndroidModel.java +30 -33
  8. package/android/src/main/java/app/notifee/core/model/NotificationAndroidStyleModel.java +6 -4
  9. package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +7 -4
  10. package/android/src/main/java/app/notifee/core/utility/BundleValueReader.java +65 -0
  11. package/android/src/main/java/app/notifee/core/utility/ObjectUtils.java +1 -1
  12. package/android/src/main/java/app/notifee/core/utility/ParcelableCompatReader.java +64 -0
  13. package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +1 -1
  14. package/android/src/main/kotlin/io/invertase/notifee/NotifeeInitProvider.kt +0 -26
  15. package/android/src/test/java/app/notifee/core/NotifeeAlarmManagerCurrentBehaviorTest.java +446 -0
  16. package/android/src/test/java/app/notifee/core/NotificationManagerCreateTriggerNotificationCurrentBehaviorTest.java +203 -0
  17. package/android/src/test/java/app/notifee/core/NotificationManagerPressActionOptOutTest.java +180 -0
  18. package/android/src/test/java/app/notifee/core/NotificationReceiverHandlerInitialNotificationTest.java +157 -0
  19. package/android/src/test/java/app/notifee/core/ReceiverServiceInitialNotificationTest.java +169 -0
  20. package/android/src/test/java/app/notifee/core/model/ChannelModelTest.java +116 -0
  21. package/android/src/test/java/app/notifee/core/model/IntervalTriggerModelTest.java +71 -0
  22. package/android/src/test/java/app/notifee/core/model/NotificationAndroidModelTest.java +309 -0
  23. package/android/src/test/java/app/notifee/core/model/NotificationAndroidStyleModelTest.java +154 -0
  24. package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +292 -6
  25. package/android/src/test/java/app/notifee/core/utility/BundleValueReaderTest.java +131 -0
  26. package/android/src/test/java/app/notifee/core/utility/ObjectUtilsTest.java +142 -0
  27. package/android/src/test/java/app/notifee/core/utility/ParcelableCompatReaderTest.java +124 -0
  28. package/android/src/test/java/io/invertase/notifee/HeadlessTaskReactHostTest.java +136 -0
  29. package/android/src/test/java/io/invertase/notifee/NotifeeEventSubscriberRoutingTest.java +262 -0
  30. package/android/src/test/java/io/invertase/notifee/NotifeeReactUtilsDrawerTest.java +24 -0
  31. package/dist/types/Notification.d.ts +5 -2
  32. package/dist/types/Notification.js +5 -2
  33. package/dist/types/Notification.js.map +1 -1
  34. package/dist/types/NotificationAndroid.d.ts +4 -0
  35. package/dist/types/NotificationAndroid.js +4 -0
  36. package/dist/types/NotificationAndroid.js.map +1 -1
  37. package/dist/version.d.ts +1 -1
  38. package/dist/version.js +1 -1
  39. package/package.json +1 -1
  40. package/src/types/Notification.ts +5 -2
  41. package/src/types/NotificationAndroid.ts +4 -0
  42. package/src/version.ts +1 -1
@@ -0,0 +1,309 @@
1
+ package app.notifee.core.model;
2
+
3
+ import static org.junit.Assert.assertArrayEquals;
4
+ import static org.junit.Assert.assertEquals;
5
+ import static org.junit.Assert.assertNotNull;
6
+ import static org.junit.Assert.assertNull;
7
+ import static org.junit.Assert.assertThrows;
8
+
9
+ import android.content.pm.ServiceInfo;
10
+ import android.graphics.Color;
11
+ import android.os.Bundle;
12
+ import androidx.core.app.NotificationCompat;
13
+ import androidx.core.app.NotificationManagerCompat;
14
+ import java.util.ArrayList;
15
+ import org.junit.Test;
16
+ import org.junit.runner.RunWith;
17
+ import org.robolectric.RobolectricTestRunner;
18
+ import org.robolectric.annotation.Config;
19
+
20
+ @RunWith(RobolectricTestRunner.class)
21
+ public class NotificationAndroidModelTest {
22
+
23
+ @Test
24
+ public void numericFields_whenMissing_returnCurrentDefaults() {
25
+ NotificationAndroidModel model = NotificationAndroidModel.fromBundle(new Bundle());
26
+
27
+ assertEquals(NotificationCompat.BADGE_ICON_LARGE, model.getBadgeIconType().intValue());
28
+ assertEquals(NotificationCompat.GROUP_ALERT_ALL, model.getGroupAlertBehaviour());
29
+ assertNull(model.getNumber());
30
+ assertEquals(NotificationCompat.PRIORITY_DEFAULT, model.getPriority());
31
+ assertNull(model.getProgress());
32
+ assertNull(model.getTimeoutAfter());
33
+ assertEquals(NotificationCompat.VISIBILITY_PRIVATE, model.getVisibility());
34
+ assertEquals(-1L, model.getTimestamp());
35
+ }
36
+
37
+ @Test
38
+ public void numericFields_withIntegerAndLongValues_returnParsedValues() {
39
+ Bundle progress = new Bundle();
40
+ progress.putInt("max", 100);
41
+ progress.putInt("current", 40);
42
+ progress.putBoolean("indeterminate", true);
43
+
44
+ Bundle bundle = new Bundle();
45
+ bundle.putInt("badgeIconType", NotificationCompat.BADGE_ICON_SMALL);
46
+ bundle.putInt("groupAlertBehavior", NotificationCompat.GROUP_ALERT_SUMMARY);
47
+ bundle.putInt("badgeCount", 8);
48
+ bundle.putInt("importance", NotificationManagerCompat.IMPORTANCE_HIGH);
49
+ bundle.putBundle("progress", progress);
50
+ bundle.putLong("timeoutAfter", 5000L);
51
+ bundle.putInt("visibility", NotificationCompat.VISIBILITY_SECRET);
52
+ bundle.putLong("timestamp", 123456789L);
53
+
54
+ NotificationAndroidModel model = NotificationAndroidModel.fromBundle(bundle);
55
+
56
+ assertEquals(NotificationCompat.BADGE_ICON_SMALL, model.getBadgeIconType().intValue());
57
+ assertEquals(NotificationCompat.GROUP_ALERT_SUMMARY, model.getGroupAlertBehaviour());
58
+ assertEquals(8, model.getNumber().intValue());
59
+ assertEquals(NotificationCompat.PRIORITY_HIGH, model.getPriority());
60
+ assertNotNull(model.getProgress());
61
+ assertEquals(100, model.getProgress().getMax());
62
+ assertEquals(40, model.getProgress().getCurrent());
63
+ assertEquals(true, model.getProgress().getIndeterminate());
64
+ assertEquals(5000L, model.getTimeoutAfter().longValue());
65
+ assertEquals(NotificationCompat.VISIBILITY_SECRET, model.getVisibility());
66
+ assertEquals(123456789L, model.getTimestamp());
67
+ }
68
+
69
+ @Test
70
+ public void numericFields_withDoubleValues_truncateWhereCurrentObjectUtilsSupportsDouble() {
71
+ Bundle progress = new Bundle();
72
+ progress.putDouble("max", 100.9d);
73
+ progress.putDouble("current", 40.8d);
74
+
75
+ Bundle bundle = new Bundle();
76
+ bundle.putDouble("badgeIconType", 1.9d);
77
+ bundle.putDouble("groupAlertBehavior", 2.9d);
78
+ bundle.putDouble("badgeCount", 8.9d);
79
+ bundle.putDouble("importance", NotificationManagerCompat.IMPORTANCE_HIGH + 0.9d);
80
+ bundle.putBundle("progress", progress);
81
+ bundle.putDouble("timeoutAfter", 5000.9d);
82
+ bundle.putDouble("visibility", -1.9d);
83
+ bundle.putDouble("timestamp", 123456789.9d);
84
+
85
+ NotificationAndroidModel model = NotificationAndroidModel.fromBundle(bundle);
86
+
87
+ assertEquals(1, model.getBadgeIconType().intValue());
88
+ assertEquals(2, model.getGroupAlertBehaviour());
89
+ assertEquals(8, model.getNumber().intValue());
90
+ assertEquals(NotificationCompat.PRIORITY_HIGH, model.getPriority());
91
+ assertNotNull(model.getProgress());
92
+ assertEquals(100, model.getProgress().getMax());
93
+ assertEquals(40, model.getProgress().getCurrent());
94
+ assertEquals(5000L, model.getTimeoutAfter().longValue());
95
+ assertEquals(NotificationCompat.VISIBILITY_SECRET, model.getVisibility());
96
+ assertEquals(123456789L, model.getTimestamp());
97
+ }
98
+
99
+ @Test
100
+ public void intBackedNumericFields_withExplicitNull_currentlyCoerceToZero() {
101
+ Bundle progress = new Bundle();
102
+ progress.putString("max", null);
103
+ progress.putString("current", null);
104
+
105
+ Bundle bundle = new Bundle();
106
+ bundle.putString("badgeIconType", null);
107
+ bundle.putString("groupAlertBehavior", null);
108
+ bundle.putString("badgeCount", null);
109
+ bundle.putBundle("progress", progress);
110
+ bundle.putString("visibility", null);
111
+
112
+ NotificationAndroidModel model = NotificationAndroidModel.fromBundle(bundle);
113
+
114
+ assertEquals(0, model.getBadgeIconType().intValue());
115
+ assertEquals(0, model.getGroupAlertBehaviour());
116
+ assertEquals(0, model.getNumber().intValue());
117
+ assertNotNull(model.getProgress());
118
+ assertEquals(0, model.getProgress().getMax());
119
+ assertEquals(0, model.getProgress().getCurrent());
120
+ assertEquals(0, model.getVisibility());
121
+ }
122
+
123
+ @Test
124
+ public void longBackedNumericFields_withExplicitNull_currentlyThrowNullPointerException() {
125
+ Bundle timeoutBundle = new Bundle();
126
+ timeoutBundle.putString("timeoutAfter", null);
127
+ assertThrows(
128
+ NullPointerException.class,
129
+ () -> NotificationAndroidModel.fromBundle(timeoutBundle).getTimeoutAfter());
130
+
131
+ Bundle timestampBundle = new Bundle();
132
+ timestampBundle.putString("timestamp", null);
133
+ assertThrows(
134
+ NullPointerException.class,
135
+ () -> NotificationAndroidModel.fromBundle(timestampBundle).getTimestamp());
136
+ }
137
+
138
+ @Test
139
+ public void numericFields_withUnsupportedNumericTypes_currentlyThrowClassCastException() {
140
+ Bundle badgeBundle = new Bundle();
141
+ badgeBundle.putLong("badgeIconType", 1L);
142
+ assertThrows(
143
+ ClassCastException.class,
144
+ () -> NotificationAndroidModel.fromBundle(badgeBundle).getBadgeIconType());
145
+
146
+ Bundle timestampBundle = new Bundle();
147
+ timestampBundle.putInt("timestamp", 1);
148
+ assertThrows(
149
+ ClassCastException.class,
150
+ () -> NotificationAndroidModel.fromBundle(timestampBundle).getTimestamp());
151
+
152
+ Bundle timeoutBundle = new Bundle();
153
+ timeoutBundle.putString("timeoutAfter", "5000");
154
+ assertThrows(
155
+ ClassCastException.class,
156
+ () -> NotificationAndroidModel.fromBundle(timeoutBundle).getTimeoutAfter());
157
+ }
158
+
159
+ @Test
160
+ public void actions_missingEmptyAndPresent_preserveParcelableArrayListBehavior() {
161
+ assertNull(NotificationAndroidModel.fromBundle(new Bundle()).getActions());
162
+
163
+ Bundle emptyBundle = new Bundle();
164
+ putRawParcelableArrayList(emptyBundle, "actions", new ArrayList<Bundle>());
165
+ assertEquals(0, NotificationAndroidModel.fromBundle(emptyBundle).getActions().size());
166
+
167
+ Bundle pressAction = new Bundle();
168
+ pressAction.putString("id", "reply");
169
+ Bundle action = new Bundle();
170
+ action.putString("title", "Reply");
171
+ action.putString("icon", "ic_reply");
172
+ action.putBundle("pressAction", pressAction);
173
+ ArrayList<Bundle> actions = new ArrayList<>();
174
+ actions.add(action);
175
+
176
+ Bundle bundle = new Bundle();
177
+ putRawParcelableArrayList(bundle, "actions", actions);
178
+ ArrayList<NotificationAndroidActionModel> parsedActions =
179
+ NotificationAndroidModel.fromBundle(bundle).getActions();
180
+
181
+ assertNotNull(parsedActions);
182
+ assertEquals(1, parsedActions.size());
183
+ assertEquals("Reply", parsedActions.get(0).getTitle());
184
+ assertEquals("ic_reply", parsedActions.get(0).getIcon());
185
+ assertEquals("reply", parsedActions.get(0).getPressAction().getId());
186
+ }
187
+
188
+ @Test
189
+ @Config(sdk = 33)
190
+ public void foregroundServiceTypes_missingEmptyAndPresent_preserveCurrentParsing() {
191
+ assertEquals(
192
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST,
193
+ NotificationAndroidModel.fromBundle(new Bundle()).getForegroundServiceType());
194
+
195
+ Bundle emptyBundle = new Bundle();
196
+ putRawParcelableArrayList(emptyBundle, "foregroundServiceTypes", new ArrayList<Integer>());
197
+ assertEquals(
198
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST,
199
+ NotificationAndroidModel.fromBundle(emptyBundle).getForegroundServiceType());
200
+
201
+ ArrayList<Object> types = new ArrayList<>();
202
+ types.add(ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC);
203
+ types.add(Double.valueOf(ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK + 0.9d));
204
+ Bundle bundle = new Bundle();
205
+ putRawParcelableArrayList(bundle, "foregroundServiceTypes", types);
206
+
207
+ assertEquals(
208
+ ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
209
+ | ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK,
210
+ NotificationAndroidModel.fromBundle(bundle).getForegroundServiceType());
211
+ }
212
+
213
+ @Test
214
+ @Config(sdk = 33)
215
+ public void foregroundServiceTypes_withUnsupportedValue_currentlyThrowsClassCastException() {
216
+ ArrayList<Object> types = new ArrayList<>();
217
+ types.add(Long.valueOf(ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC));
218
+ Bundle bundle = new Bundle();
219
+ putRawParcelableArrayList(bundle, "foregroundServiceTypes", types);
220
+
221
+ assertThrows(
222
+ ClassCastException.class,
223
+ () -> NotificationAndroidModel.fromBundle(bundle).getForegroundServiceType());
224
+ }
225
+
226
+ @Test
227
+ public void lights_missingValidAndInvalidValues_preserveCurrentNullOnParseFailure() {
228
+ assertNull(NotificationAndroidModel.fromBundle(new Bundle()).getLights());
229
+
230
+ ArrayList<Object> lights = new ArrayList<>();
231
+ lights.add("#112233");
232
+ lights.add(100);
233
+ lights.add(200);
234
+ Bundle validBundle = new Bundle();
235
+ putRawParcelableArrayList(validBundle, "lights", lights);
236
+
237
+ ArrayList<Integer> parsedLights = NotificationAndroidModel.fromBundle(validBundle).getLights();
238
+ assertNotNull(parsedLights);
239
+ assertEquals(Color.parseColor("#112233"), parsedLights.get(0).intValue());
240
+ assertEquals(100, parsedLights.get(1).intValue());
241
+ assertEquals(200, parsedLights.get(2).intValue());
242
+
243
+ ArrayList<Object> invalidDuration = new ArrayList<>();
244
+ invalidDuration.add("#112233");
245
+ invalidDuration.add(100L);
246
+ invalidDuration.add(200);
247
+ Bundle invalidBundle = new Bundle();
248
+ putRawParcelableArrayList(invalidBundle, "lights", invalidDuration);
249
+
250
+ assertNull(NotificationAndroidModel.fromBundle(invalidBundle).getLights());
251
+ }
252
+
253
+ @Test
254
+ public void flags_missingValidAndUnsupportedValues_preserveCurrentBehavior() {
255
+ assertNull(NotificationAndroidModel.fromBundle(new Bundle()).getFlags());
256
+
257
+ ArrayList<Object> flags = new ArrayList<>();
258
+ flags.add(1);
259
+ flags.add(2.9d);
260
+ Bundle validBundle = new Bundle();
261
+ putRawParcelableArrayList(validBundle, "flags", flags);
262
+
263
+ assertArrayEquals(new int[] {1, 2}, NotificationAndroidModel.fromBundle(validBundle).getFlags());
264
+
265
+ ArrayList<Object> invalidFlags = new ArrayList<>();
266
+ invalidFlags.add(1L);
267
+ Bundle invalidBundle = new Bundle();
268
+ putRawParcelableArrayList(invalidBundle, "flags", invalidFlags);
269
+
270
+ assertThrows(
271
+ ClassCastException.class,
272
+ () -> NotificationAndroidModel.fromBundle(invalidBundle).getFlags());
273
+ }
274
+
275
+ @Test
276
+ public void vibrationPattern_missingEmptyIntegerAndUnsupportedValues_preserveCurrentBehavior() {
277
+ assertArrayEquals(new long[0], NotificationAndroidModel.fromBundle(new Bundle()).getVibrationPattern());
278
+
279
+ Bundle emptyBundle = new Bundle();
280
+ putRawParcelableArrayList(emptyBundle, "vibrationPattern", new ArrayList<Integer>());
281
+ assertArrayEquals(
282
+ new long[0], NotificationAndroidModel.fromBundle(emptyBundle).getVibrationPattern());
283
+
284
+ ArrayList<Integer> vibrationPattern = new ArrayList<>();
285
+ vibrationPattern.add(100);
286
+ vibrationPattern.add(200);
287
+ Bundle validBundle = new Bundle();
288
+ putRawParcelableArrayList(validBundle, "vibrationPattern", vibrationPattern);
289
+
290
+ assertArrayEquals(
291
+ new long[] {100L, 200L},
292
+ NotificationAndroidModel.fromBundle(validBundle).getVibrationPattern());
293
+
294
+ ArrayList<Object> invalidPattern = new ArrayList<>();
295
+ invalidPattern.add(100L);
296
+ Bundle invalidBundle = new Bundle();
297
+ putRawParcelableArrayList(invalidBundle, "vibrationPattern", invalidPattern);
298
+
299
+ assertThrows(
300
+ ClassCastException.class,
301
+ () -> NotificationAndroidModel.fromBundle(invalidBundle).getVibrationPattern());
302
+ }
303
+
304
+ @SuppressWarnings({"rawtypes", "unchecked"})
305
+ private static void putRawParcelableArrayList(
306
+ Bundle bundle, String key, ArrayList<?> arrayList) {
307
+ bundle.putParcelableArrayList(key, (ArrayList) arrayList);
308
+ }
309
+ }
@@ -0,0 +1,154 @@
1
+ package app.notifee.core.model;
2
+
3
+ import static org.junit.Assert.assertEquals;
4
+ import static org.junit.Assert.assertNotNull;
5
+ import static org.junit.Assert.assertThrows;
6
+ import static org.junit.Assert.assertTrue;
7
+
8
+ import android.os.Bundle;
9
+ import androidx.core.app.NotificationCompat;
10
+ import com.google.common.util.concurrent.ListenableFuture;
11
+ import com.google.common.util.concurrent.ListeningExecutorService;
12
+ import com.google.common.util.concurrent.MoreExecutors;
13
+ import java.util.ArrayList;
14
+ import java.util.List;
15
+ import java.util.concurrent.ExecutionException;
16
+ import org.junit.After;
17
+ import org.junit.Before;
18
+ import org.junit.Test;
19
+ import org.junit.runner.RunWith;
20
+ import org.robolectric.RobolectricTestRunner;
21
+
22
+ @RunWith(RobolectricTestRunner.class)
23
+ public class NotificationAndroidStyleModelTest {
24
+ private ListeningExecutorService executor;
25
+
26
+ @Before
27
+ public void setUp() {
28
+ executor = MoreExecutors.newDirectExecutorService();
29
+ }
30
+
31
+ @After
32
+ public void tearDown() {
33
+ executor.shutdownNow();
34
+ }
35
+
36
+ @Test
37
+ public void getStyleTask_missingType_currentlyDefaultsToBigPictureStyle() throws Exception {
38
+ NotificationCompat.Style style =
39
+ NotificationAndroidStyleModel.fromBundle(new Bundle()).getStyleTask(executor).get();
40
+
41
+ assertTrue(style instanceof NotificationCompat.BigPictureStyle);
42
+ }
43
+
44
+ @Test
45
+ public void getStyleTask_integerAndDoubleType_preserveCurrentTypeParsing() throws Exception {
46
+ Bundle bigTextBundle = new Bundle();
47
+ bigTextBundle.putInt("type", 1);
48
+ NotificationCompat.Style bigTextStyle =
49
+ NotificationAndroidStyleModel.fromBundle(bigTextBundle).getStyleTask(executor).get();
50
+ assertTrue(bigTextStyle instanceof NotificationCompat.BigTextStyle);
51
+
52
+ Bundle truncatedDoubleBundle = new Bundle();
53
+ truncatedDoubleBundle.putDouble("type", 1.9d);
54
+ NotificationCompat.Style truncatedStyle =
55
+ NotificationAndroidStyleModel.fromBundle(truncatedDoubleBundle).getStyleTask(executor).get();
56
+ assertTrue(truncatedStyle instanceof NotificationCompat.BigTextStyle);
57
+ }
58
+
59
+ @Test
60
+ public void getStyleTask_wrongType_currentlyThrowsClassCastExceptionSynchronously() {
61
+ Bundle bundle = new Bundle();
62
+ bundle.putString("type", "1");
63
+
64
+ assertThrows(
65
+ ClassCastException.class,
66
+ () -> NotificationAndroidStyleModel.fromBundle(bundle).getStyleTask(executor));
67
+ }
68
+
69
+ @Test
70
+ public void messagingStyle_withMessages_preservesParcelableArrayListAndTimestampParsing()
71
+ throws Exception {
72
+ Bundle bundle = baseMessagingStyleBundle();
73
+ ArrayList<Bundle> messages = new ArrayList<>();
74
+ messages.add(messageBundle("first", 123L, personBundle("Alice")));
75
+ messages.add(messageBundle("second", 456.9d, null));
76
+ putRawParcelableArrayList(bundle, "messages", messages);
77
+
78
+ NotificationCompat.Style style =
79
+ NotificationAndroidStyleModel.fromBundle(bundle).getStyleTask(executor).get();
80
+
81
+ assertTrue(style instanceof NotificationCompat.MessagingStyle);
82
+ NotificationCompat.MessagingStyle messagingStyle = (NotificationCompat.MessagingStyle) style;
83
+ List<NotificationCompat.MessagingStyle.Message> parsedMessages = messagingStyle.getMessages();
84
+
85
+ assertEquals(2, parsedMessages.size());
86
+ assertEquals("first", parsedMessages.get(0).getText().toString());
87
+ assertEquals(123L, parsedMessages.get(0).getTimestamp());
88
+ assertNotNull(parsedMessages.get(0).getPerson());
89
+ assertEquals("Alice", parsedMessages.get(0).getPerson().getName().toString());
90
+ assertEquals("second", parsedMessages.get(1).getText().toString());
91
+ assertEquals(456L, parsedMessages.get(1).getTimestamp());
92
+ }
93
+
94
+ @Test
95
+ public void messagingStyle_missingMessages_currentlyFailsInsideFuture() {
96
+ Bundle bundle = baseMessagingStyleBundle();
97
+
98
+ ListenableFuture<NotificationCompat.Style> future =
99
+ NotificationAndroidStyleModel.fromBundle(bundle).getStyleTask(executor);
100
+
101
+ ExecutionException exception = assertThrows(ExecutionException.class, future::get);
102
+ assertTrue(exception.getCause() instanceof NullPointerException);
103
+ }
104
+
105
+ @Test
106
+ public void messagingStyle_integerTimestamp_currentlyFailsInsideFuture() {
107
+ Bundle bundle = baseMessagingStyleBundle();
108
+ ArrayList<Bundle> messages = new ArrayList<>();
109
+ Bundle message = new Bundle();
110
+ message.putString("text", "integer timestamp");
111
+ message.putInt("timestamp", 123);
112
+ messages.add(message);
113
+ putRawParcelableArrayList(bundle, "messages", messages);
114
+
115
+ ListenableFuture<NotificationCompat.Style> future =
116
+ NotificationAndroidStyleModel.fromBundle(bundle).getStyleTask(executor);
117
+
118
+ ExecutionException exception = assertThrows(ExecutionException.class, future::get);
119
+ assertTrue(exception.getCause() instanceof ClassCastException);
120
+ }
121
+
122
+ private static Bundle baseMessagingStyleBundle() {
123
+ Bundle bundle = new Bundle();
124
+ bundle.putInt("type", 3);
125
+ bundle.putBundle("person", personBundle("Me"));
126
+ return bundle;
127
+ }
128
+
129
+ private static Bundle personBundle(String name) {
130
+ Bundle person = new Bundle();
131
+ person.putString("name", name);
132
+ return person;
133
+ }
134
+
135
+ private static Bundle messageBundle(String text, Object timestamp, Bundle person) {
136
+ Bundle message = new Bundle();
137
+ message.putString("text", text);
138
+ if (timestamp instanceof Long) {
139
+ message.putLong("timestamp", (Long) timestamp);
140
+ } else if (timestamp instanceof Double) {
141
+ message.putDouble("timestamp", (Double) timestamp);
142
+ }
143
+ if (person != null) {
144
+ message.putBundle("person", person);
145
+ }
146
+ return message;
147
+ }
148
+
149
+ @SuppressWarnings({"rawtypes", "unchecked"})
150
+ private static void putRawParcelableArrayList(
151
+ Bundle bundle, String key, ArrayList<?> arrayList) {
152
+ bundle.putParcelableArrayList(key, (ArrayList) arrayList);
153
+ }
154
+ }