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.
- package/android/src/main/java/app/notifee/core/ForegroundService.java +3 -1
- package/android/src/main/java/app/notifee/core/NotifeeAlarmManager.java +4 -2
- package/android/src/main/java/app/notifee/core/NotificationManager.java +28 -35
- package/android/src/main/java/app/notifee/core/database/NotifeeCoreDatabase.java +1 -4
- package/android/src/main/java/app/notifee/core/model/ChannelModel.java +8 -13
- package/android/src/main/java/app/notifee/core/model/IntervalTriggerModel.java +2 -6
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidModel.java +30 -33
- package/android/src/main/java/app/notifee/core/model/NotificationAndroidStyleModel.java +6 -4
- package/android/src/main/java/app/notifee/core/model/TimestampTriggerModel.java +7 -4
- package/android/src/main/java/app/notifee/core/utility/BundleValueReader.java +65 -0
- package/android/src/main/java/app/notifee/core/utility/ObjectUtils.java +1 -1
- package/android/src/main/java/app/notifee/core/utility/ParcelableCompatReader.java +64 -0
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeApiModule.kt +1 -1
- package/android/src/main/kotlin/io/invertase/notifee/NotifeeInitProvider.kt +0 -26
- package/android/src/test/java/app/notifee/core/NotifeeAlarmManagerCurrentBehaviorTest.java +446 -0
- package/android/src/test/java/app/notifee/core/NotificationManagerCreateTriggerNotificationCurrentBehaviorTest.java +203 -0
- package/android/src/test/java/app/notifee/core/NotificationManagerPressActionOptOutTest.java +180 -0
- package/android/src/test/java/app/notifee/core/NotificationReceiverHandlerInitialNotificationTest.java +157 -0
- package/android/src/test/java/app/notifee/core/ReceiverServiceInitialNotificationTest.java +169 -0
- package/android/src/test/java/app/notifee/core/model/ChannelModelTest.java +116 -0
- package/android/src/test/java/app/notifee/core/model/IntervalTriggerModelTest.java +71 -0
- package/android/src/test/java/app/notifee/core/model/NotificationAndroidModelTest.java +309 -0
- package/android/src/test/java/app/notifee/core/model/NotificationAndroidStyleModelTest.java +154 -0
- package/android/src/test/java/app/notifee/core/model/TimestampTriggerModelTest.java +292 -6
- package/android/src/test/java/app/notifee/core/utility/BundleValueReaderTest.java +131 -0
- package/android/src/test/java/app/notifee/core/utility/ObjectUtilsTest.java +142 -0
- package/android/src/test/java/app/notifee/core/utility/ParcelableCompatReaderTest.java +124 -0
- package/android/src/test/java/io/invertase/notifee/HeadlessTaskReactHostTest.java +136 -0
- package/android/src/test/java/io/invertase/notifee/NotifeeEventSubscriberRoutingTest.java +262 -0
- package/android/src/test/java/io/invertase/notifee/NotifeeReactUtilsDrawerTest.java +24 -0
- package/dist/types/Notification.d.ts +5 -2
- package/dist/types/Notification.js +5 -2
- package/dist/types/Notification.js.map +1 -1
- package/dist/types/NotificationAndroid.d.ts +4 -0
- package/dist/types/NotificationAndroid.js +4 -0
- package/dist/types/NotificationAndroid.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/types/Notification.ts +5 -2
- package/src/types/NotificationAndroid.ts +4 -0
- package/src/version.ts +1 -1
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
package app.notifee.core.model;
|
|
2
2
|
|
|
3
3
|
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertFalse;
|
|
4
5
|
import static org.junit.Assert.assertNull;
|
|
6
|
+
import static org.junit.Assert.assertThrows;
|
|
5
7
|
import static org.junit.Assert.assertTrue;
|
|
6
8
|
|
|
7
9
|
import android.os.Bundle;
|
|
@@ -56,22 +58,24 @@ public class TimestampTriggerModelTest {
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
@Test
|
|
59
|
-
public void
|
|
61
|
+
public void repeatFrequency_missingLeavesNonRepeatingDefaults() {
|
|
60
62
|
assertEquals(
|
|
61
63
|
"with no 'repeatFrequency', interval should be -1",
|
|
62
64
|
-1,
|
|
63
65
|
mTimestampTriggerModel.getInterval());
|
|
64
66
|
assertNull(
|
|
65
67
|
"with no 'repeatFrequency', TimeUnit should be null", mTimestampTriggerModel.getTimeUnit());
|
|
68
|
+
assertNull(
|
|
69
|
+
"with no 'repeatFrequency', repeat frequency should be null",
|
|
70
|
+
mTimestampTriggerModel.getRepeatFrequency());
|
|
66
71
|
assertEquals(
|
|
67
72
|
"with no 'repeatFrequency', delay should be 0", 0, mTimestampTriggerModel.getDelay());
|
|
73
|
+
assertThrows(
|
|
74
|
+
"with no 'repeatFrequency', timestamp remains null",
|
|
75
|
+
NullPointerException.class,
|
|
76
|
+
() -> mTimestampTriggerModel.getTimestamp());
|
|
68
77
|
}
|
|
69
78
|
|
|
70
|
-
// Regression tests for the DAILY/WEEKLY/HOURLY rescheduling cycle. Guard the fix for
|
|
71
|
-
// upstream invertase/notifee#839 (DAILY trigger fails to re-fire from day 2 onwards on
|
|
72
|
-
// Android) and #875 (DST-safe Calendar.add for repeat frequency) against future refactors
|
|
73
|
-
// of TimestampTriggerModel.setNextTimestamp().
|
|
74
|
-
|
|
75
79
|
private TimestampTriggerModel buildRepeatingTrigger(long timestamp, int repeatFrequency) {
|
|
76
80
|
Bundle trigger = new Bundle();
|
|
77
81
|
trigger.putLong("timestamp", timestamp);
|
|
@@ -88,6 +92,42 @@ public class TimestampTriggerModelTest {
|
|
|
88
92
|
return TimestampTriggerModel.fromBundle(trigger);
|
|
89
93
|
}
|
|
90
94
|
|
|
95
|
+
private Bundle buildRepeatingTriggerBundle() {
|
|
96
|
+
Bundle trigger = new Bundle();
|
|
97
|
+
trigger.putLong("timestamp", mNow + ONE_DAY_MS);
|
|
98
|
+
trigger.putInt("repeatFrequency", REPEAT_FREQUENCY_DAILY);
|
|
99
|
+
return trigger;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private TimestampTriggerModel buildTriggerWithRepeatFrequencyValue(Object repeatFrequency) {
|
|
103
|
+
Bundle trigger = new Bundle();
|
|
104
|
+
trigger.putLong("timestamp", mNow + ONE_DAY_MS);
|
|
105
|
+
putBundleValue(trigger, "repeatFrequency", repeatFrequency);
|
|
106
|
+
return TimestampTriggerModel.fromBundle(trigger);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private TimestampTriggerModel buildTriggerWithRepeatIntervalValue(Object repeatInterval) {
|
|
110
|
+
Bundle trigger = buildRepeatingTriggerBundle();
|
|
111
|
+
putBundleValue(trigger, "repeatInterval", repeatInterval);
|
|
112
|
+
return TimestampTriggerModel.fromBundle(trigger);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private TimestampTriggerModel buildTriggerWithTimestampValue(Object timestamp) {
|
|
116
|
+
Bundle trigger = new Bundle();
|
|
117
|
+
trigger.putInt("repeatFrequency", REPEAT_FREQUENCY_DAILY);
|
|
118
|
+
putBundleValue(trigger, "timestamp", timestamp);
|
|
119
|
+
return TimestampTriggerModel.fromBundle(trigger);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private TimestampTriggerModel buildTriggerWithAlarmManagerTypeValue(Object type) {
|
|
123
|
+
Bundle alarmManager = new Bundle();
|
|
124
|
+
putBundleValue(alarmManager, "type", type);
|
|
125
|
+
|
|
126
|
+
Bundle trigger = new Bundle();
|
|
127
|
+
trigger.putBundle("alarmManager", alarmManager);
|
|
128
|
+
return TimestampTriggerModel.fromBundle(trigger);
|
|
129
|
+
}
|
|
130
|
+
|
|
91
131
|
private long expectedNextTimestamp(long timestamp, int field, int repeatInterval) {
|
|
92
132
|
Calendar cal = Calendar.getInstance();
|
|
93
133
|
cal.setTimeInMillis(timestamp);
|
|
@@ -97,6 +137,252 @@ public class TimestampTriggerModelTest {
|
|
|
97
137
|
return cal.getTimeInMillis();
|
|
98
138
|
}
|
|
99
139
|
|
|
140
|
+
private static void putBundleValue(Bundle bundle, String key, Object value) {
|
|
141
|
+
if (value == null) {
|
|
142
|
+
bundle.putString(key, null);
|
|
143
|
+
} else if (value instanceof Integer) {
|
|
144
|
+
bundle.putInt(key, (Integer) value);
|
|
145
|
+
} else if (value instanceof Long) {
|
|
146
|
+
bundle.putLong(key, (Long) value);
|
|
147
|
+
} else if (value instanceof Float) {
|
|
148
|
+
bundle.putFloat(key, (Float) value);
|
|
149
|
+
} else if (value instanceof Double) {
|
|
150
|
+
bundle.putDouble(key, (Double) value);
|
|
151
|
+
} else if (value instanceof String) {
|
|
152
|
+
bundle.putString(key, (String) value);
|
|
153
|
+
} else if (value instanceof Boolean) {
|
|
154
|
+
bundle.putBoolean(key, (Boolean) value);
|
|
155
|
+
} else {
|
|
156
|
+
throw new IllegalArgumentException("Unsupported bundle test value: " + value.getClass());
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
@Test
|
|
161
|
+
public void repeatFrequency_explicitNullUsesHourlyWhenTimestampIsValid() {
|
|
162
|
+
long timestamp = mNow + ONE_DAY_MS;
|
|
163
|
+
Bundle trigger = new Bundle();
|
|
164
|
+
trigger.putLong("timestamp", timestamp);
|
|
165
|
+
trigger.putString("repeatFrequency", null);
|
|
166
|
+
|
|
167
|
+
TimestampTriggerModel model = TimestampTriggerModel.fromBundle(trigger);
|
|
168
|
+
|
|
169
|
+
assertEquals(TimestampTriggerModel.HOURLY, model.getRepeatFrequency());
|
|
170
|
+
assertEquals(1, model.getInterval());
|
|
171
|
+
assertEquals(TimeUnit.HOURS, model.getTimeUnit());
|
|
172
|
+
assertEquals(timestamp, model.getTimestamp());
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@Test
|
|
176
|
+
public void repeatFrequency_integerValuesMapToCurrentRepeatModes() {
|
|
177
|
+
TimestampTriggerModel oneTime = buildTriggerWithRepeatFrequencyValue(-1);
|
|
178
|
+
assertNull(oneTime.getRepeatFrequency());
|
|
179
|
+
assertEquals(-1, oneTime.getInterval());
|
|
180
|
+
assertNull(oneTime.getTimeUnit());
|
|
181
|
+
|
|
182
|
+
TimestampTriggerModel hourly = buildTriggerWithRepeatFrequencyValue(REPEAT_FREQUENCY_HOURLY);
|
|
183
|
+
assertEquals(TimestampTriggerModel.HOURLY, hourly.getRepeatFrequency());
|
|
184
|
+
assertEquals(1, hourly.getInterval());
|
|
185
|
+
assertEquals(TimeUnit.HOURS, hourly.getTimeUnit());
|
|
186
|
+
|
|
187
|
+
TimestampTriggerModel daily = buildTriggerWithRepeatFrequencyValue(REPEAT_FREQUENCY_DAILY);
|
|
188
|
+
assertEquals(TimestampTriggerModel.DAILY, daily.getRepeatFrequency());
|
|
189
|
+
assertEquals(1, daily.getInterval());
|
|
190
|
+
assertEquals(TimeUnit.DAYS, daily.getTimeUnit());
|
|
191
|
+
|
|
192
|
+
TimestampTriggerModel weekly = buildTriggerWithRepeatFrequencyValue(REPEAT_FREQUENCY_WEEKLY);
|
|
193
|
+
assertEquals(TimestampTriggerModel.WEEKLY, weekly.getRepeatFrequency());
|
|
194
|
+
assertEquals(7, weekly.getInterval());
|
|
195
|
+
assertEquals(TimeUnit.DAYS, weekly.getTimeUnit());
|
|
196
|
+
|
|
197
|
+
TimestampTriggerModel monthly = buildTriggerWithRepeatFrequencyValue(REPEAT_FREQUENCY_MONTHLY);
|
|
198
|
+
assertEquals(TimestampTriggerModel.MONTHLY, monthly.getRepeatFrequency());
|
|
199
|
+
assertEquals(-1, monthly.getInterval());
|
|
200
|
+
assertNull(monthly.getTimeUnit());
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@Test
|
|
204
|
+
public void repeatFrequency_truncatesDoubleValue() {
|
|
205
|
+
TimestampTriggerModel model = buildTriggerWithRepeatFrequencyValue(2.9d);
|
|
206
|
+
|
|
207
|
+
assertEquals(TimestampTriggerModel.WEEKLY, model.getRepeatFrequency());
|
|
208
|
+
assertEquals(7, model.getInterval());
|
|
209
|
+
assertEquals(TimeUnit.DAYS, model.getTimeUnit());
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
@Test
|
|
213
|
+
public void repeatFrequency_preservesClassCastForUnsupportedTypes() {
|
|
214
|
+
assertThrows(
|
|
215
|
+
ClassCastException.class, () -> buildTriggerWithRepeatFrequencyValue(Long.valueOf(0L)));
|
|
216
|
+
assertThrows(
|
|
217
|
+
ClassCastException.class, () -> buildTriggerWithRepeatFrequencyValue(Float.valueOf(0.0f)));
|
|
218
|
+
assertThrows(ClassCastException.class, () -> buildTriggerWithRepeatFrequencyValue("0"));
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
@Test
|
|
222
|
+
public void repeatInterval_missingNullAndNonNumberDefaultToOne() {
|
|
223
|
+
assertEquals(1, TimestampTriggerModel.fromBundle(buildRepeatingTriggerBundle()).getInterval());
|
|
224
|
+
assertEquals(1, buildTriggerWithRepeatIntervalValue(null).getInterval());
|
|
225
|
+
assertEquals(1, buildTriggerWithRepeatIntervalValue("2").getInterval());
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@Test
|
|
229
|
+
public void repeatInterval_acceptsPositiveIntegralNumbers() {
|
|
230
|
+
assertEquals(2, buildTriggerWithRepeatIntervalValue(2).getInterval());
|
|
231
|
+
assertEquals(3, buildTriggerWithRepeatIntervalValue(Long.valueOf(3L)).getInterval());
|
|
232
|
+
assertEquals(4, buildTriggerWithRepeatIntervalValue(Float.valueOf(4.0f)).getInterval());
|
|
233
|
+
assertEquals(5, buildTriggerWithRepeatIntervalValue(Double.valueOf(5.0d)).getInterval());
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
@Test
|
|
237
|
+
public void repeatInterval_rejectsZeroNegativeFractionalNaNInfinityAndOverflow() {
|
|
238
|
+
assertEquals(1, buildTriggerWithRepeatIntervalValue(0).getInterval());
|
|
239
|
+
assertEquals(1, buildTriggerWithRepeatIntervalValue(-1).getInterval());
|
|
240
|
+
assertEquals(1, buildTriggerWithRepeatIntervalValue(1.5d).getInterval());
|
|
241
|
+
assertEquals(1, buildTriggerWithRepeatIntervalValue(Double.NaN).getInterval());
|
|
242
|
+
assertEquals(1, buildTriggerWithRepeatIntervalValue(Double.POSITIVE_INFINITY).getInterval());
|
|
243
|
+
assertEquals(
|
|
244
|
+
1,
|
|
245
|
+
buildTriggerWithRepeatIntervalValue(Long.valueOf((long) Integer.MAX_VALUE + 1L))
|
|
246
|
+
.getInterval());
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@Test
|
|
250
|
+
public void timestamp_missingWithRepeatFrequencyThrowsNullPointerException() {
|
|
251
|
+
Bundle trigger = new Bundle();
|
|
252
|
+
trigger.putInt("repeatFrequency", REPEAT_FREQUENCY_DAILY);
|
|
253
|
+
|
|
254
|
+
assertThrows(NullPointerException.class, () -> TimestampTriggerModel.fromBundle(trigger));
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
@Test
|
|
258
|
+
public void timestamp_explicitNullWithRepeatFrequencyThrowsNullPointerException() {
|
|
259
|
+
Bundle trigger = new Bundle();
|
|
260
|
+
trigger.putInt("repeatFrequency", REPEAT_FREQUENCY_DAILY);
|
|
261
|
+
trigger.putString("timestamp", null);
|
|
262
|
+
|
|
263
|
+
assertThrows(NullPointerException.class, () -> TimestampTriggerModel.fromBundle(trigger));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
@Test
|
|
267
|
+
public void timestamp_longValueIsPreserved() {
|
|
268
|
+
long timestamp = 123456789L;
|
|
269
|
+
|
|
270
|
+
TimestampTriggerModel model = buildTriggerWithTimestampValue(timestamp);
|
|
271
|
+
|
|
272
|
+
assertEquals(timestamp, model.getTimestamp());
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
@Test
|
|
276
|
+
public void timestamp_truncatesDoubleValue() {
|
|
277
|
+
TimestampTriggerModel model = buildTriggerWithTimestampValue(123456789.9d);
|
|
278
|
+
|
|
279
|
+
assertEquals(123456789L, model.getTimestamp());
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@Test
|
|
283
|
+
public void timestamp_preservesClassCastForUnsupportedTypes() {
|
|
284
|
+
assertThrows(ClassCastException.class, () -> buildTriggerWithTimestampValue(1));
|
|
285
|
+
assertThrows(
|
|
286
|
+
ClassCastException.class, () -> buildTriggerWithTimestampValue(Float.valueOf(1.0f)));
|
|
287
|
+
assertThrows(ClassCastException.class, () -> buildTriggerWithTimestampValue("123456789"));
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
@Test
|
|
291
|
+
public void alarmManager_missingKeepsAlarmManagerDisabled() {
|
|
292
|
+
TimestampTriggerModel model = TimestampTriggerModel.fromBundle(new Bundle());
|
|
293
|
+
|
|
294
|
+
assertFalse(model.getWithAlarmManager());
|
|
295
|
+
assertEquals(TimestampTriggerModel.AlarmType.SET_EXACT, model.getAlarmType());
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@Test
|
|
299
|
+
public void alarmManager_nullBundlePreservesCurrentBehavior() {
|
|
300
|
+
Bundle trigger = new Bundle();
|
|
301
|
+
trigger.putBundle("alarmManager", null);
|
|
302
|
+
|
|
303
|
+
assertThrows(NullPointerException.class, () -> TimestampTriggerModel.fromBundle(trigger));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
@Test
|
|
307
|
+
public void alarmManager_missingOrNullTypeDefaultsToSetExactAllowWhileIdle() {
|
|
308
|
+
Bundle missingTypeAlarmManager = new Bundle();
|
|
309
|
+
Bundle missingTypeTrigger = new Bundle();
|
|
310
|
+
missingTypeTrigger.putBundle("alarmManager", missingTypeAlarmManager);
|
|
311
|
+
TimestampTriggerModel missingTypeModel = TimestampTriggerModel.fromBundle(missingTypeTrigger);
|
|
312
|
+
|
|
313
|
+
assertTrue(missingTypeModel.getWithAlarmManager());
|
|
314
|
+
assertEquals(
|
|
315
|
+
TimestampTriggerModel.AlarmType.SET_EXACT_AND_ALLOW_WHILE_IDLE,
|
|
316
|
+
missingTypeModel.getAlarmType());
|
|
317
|
+
|
|
318
|
+
Bundle nullTypeAlarmManager = new Bundle();
|
|
319
|
+
nullTypeAlarmManager.putString("type", null);
|
|
320
|
+
Bundle nullTypeTrigger = new Bundle();
|
|
321
|
+
nullTypeTrigger.putBundle("alarmManager", nullTypeAlarmManager);
|
|
322
|
+
TimestampTriggerModel nullTypeModel = TimestampTriggerModel.fromBundle(nullTypeTrigger);
|
|
323
|
+
|
|
324
|
+
assertTrue(nullTypeModel.getWithAlarmManager());
|
|
325
|
+
assertEquals(
|
|
326
|
+
TimestampTriggerModel.AlarmType.SET_EXACT_AND_ALLOW_WHILE_IDLE,
|
|
327
|
+
nullTypeModel.getAlarmType());
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
@Test
|
|
331
|
+
public void alarmManager_mapsIntegerTypes() {
|
|
332
|
+
TimestampTriggerModel.AlarmType[] expectedTypes =
|
|
333
|
+
new TimestampTriggerModel.AlarmType[] {
|
|
334
|
+
TimestampTriggerModel.AlarmType.SET,
|
|
335
|
+
TimestampTriggerModel.AlarmType.SET_AND_ALLOW_WHILE_IDLE,
|
|
336
|
+
TimestampTriggerModel.AlarmType.SET_EXACT,
|
|
337
|
+
TimestampTriggerModel.AlarmType.SET_EXACT_AND_ALLOW_WHILE_IDLE,
|
|
338
|
+
TimestampTriggerModel.AlarmType.SET_ALARM_CLOCK
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
for (int type = 0; type < expectedTypes.length; type++) {
|
|
342
|
+
TimestampTriggerModel model = buildTriggerWithAlarmManagerTypeValue(type);
|
|
343
|
+
|
|
344
|
+
assertTrue(model.getWithAlarmManager());
|
|
345
|
+
assertEquals(expectedTypes[type], model.getAlarmType());
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
@Test
|
|
350
|
+
public void alarmManager_truncatesDoubleType() {
|
|
351
|
+
TimestampTriggerModel model = buildTriggerWithAlarmManagerTypeValue(4.9d);
|
|
352
|
+
|
|
353
|
+
assertTrue(model.getWithAlarmManager());
|
|
354
|
+
assertEquals(TimestampTriggerModel.AlarmType.SET_ALARM_CLOCK, model.getAlarmType());
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
@Test
|
|
358
|
+
public void alarmManager_preservesClassCastForUnsupportedTypes() {
|
|
359
|
+
assertThrows(
|
|
360
|
+
ClassCastException.class, () -> buildTriggerWithAlarmManagerTypeValue(Long.valueOf(3L)));
|
|
361
|
+
assertThrows(
|
|
362
|
+
ClassCastException.class, () -> buildTriggerWithAlarmManagerTypeValue(Float.valueOf(3.0f)));
|
|
363
|
+
assertThrows(ClassCastException.class, () -> buildTriggerWithAlarmManagerTypeValue("3"));
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
@Test
|
|
367
|
+
public void alarmManager_allowWhileIdleOverridesTypeToSetExactAllowWhileIdle() {
|
|
368
|
+
Bundle alarmManager = new Bundle();
|
|
369
|
+
alarmManager.putInt("type", 4);
|
|
370
|
+
alarmManager.putBoolean("allowWhileIdle", true);
|
|
371
|
+
Bundle trigger = new Bundle();
|
|
372
|
+
trigger.putBundle("alarmManager", alarmManager);
|
|
373
|
+
|
|
374
|
+
TimestampTriggerModel model = TimestampTriggerModel.fromBundle(trigger);
|
|
375
|
+
|
|
376
|
+
assertTrue(model.getWithAlarmManager());
|
|
377
|
+
assertEquals(
|
|
378
|
+
TimestampTriggerModel.AlarmType.SET_EXACT_AND_ALLOW_WHILE_IDLE, model.getAlarmType());
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Regression tests for the DAILY/WEEKLY/HOURLY rescheduling cycle. Guard the fix for
|
|
382
|
+
// upstream invertase/notifee#839 (DAILY trigger fails to re-fire from day 2 onwards on
|
|
383
|
+
// Android) and #875 (DST-safe Calendar.add for repeat frequency) against future refactors
|
|
384
|
+
// of TimestampTriggerModel.setNextTimestamp().
|
|
385
|
+
|
|
100
386
|
@Test
|
|
101
387
|
public void repeatingTrigger_withoutRepeatInterval_defaultsToOne() {
|
|
102
388
|
TimestampTriggerModel trigger =
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
package app.notifee.core.utility;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertNull;
|
|
5
|
+
import static org.junit.Assert.assertSame;
|
|
6
|
+
import static org.junit.Assert.assertThrows;
|
|
7
|
+
|
|
8
|
+
import android.os.Bundle;
|
|
9
|
+
import java.util.ArrayList;
|
|
10
|
+
import org.junit.Test;
|
|
11
|
+
import org.junit.runner.RunWith;
|
|
12
|
+
import org.robolectric.RobolectricTestRunner;
|
|
13
|
+
|
|
14
|
+
@RunWith(RobolectricTestRunner.class)
|
|
15
|
+
public class BundleValueReaderTest {
|
|
16
|
+
|
|
17
|
+
@Test
|
|
18
|
+
public void getValue_returnsRawValueAndNullForMissingAndExplicitNull() {
|
|
19
|
+
Bundle bundle = new Bundle();
|
|
20
|
+
bundle.putString("string", "value");
|
|
21
|
+
bundle.putString("explicitNull", null);
|
|
22
|
+
|
|
23
|
+
assertEquals("value", BundleValueReader.getValue(bundle, "string"));
|
|
24
|
+
assertNull(BundleValueReader.getValue(bundle, "missing"));
|
|
25
|
+
assertNull(BundleValueReader.getValue(bundle, "explicitNull"));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Test
|
|
29
|
+
public void getValue_nullBundleThrowsNullPointerException() {
|
|
30
|
+
assertThrows(NullPointerException.class, () -> BundleValueReader.getValue(null, "key"));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Test
|
|
34
|
+
public void getIntPreserving_matchesCurrentObjectUtilsBehavior() {
|
|
35
|
+
Bundle bundle = new Bundle();
|
|
36
|
+
bundle.putInt("integer", 7);
|
|
37
|
+
bundle.putDouble("double", 7.9d);
|
|
38
|
+
bundle.putString("explicitNull", null);
|
|
39
|
+
bundle.putLong("long", 7L);
|
|
40
|
+
bundle.putFloat("float", 7.5f);
|
|
41
|
+
bundle.putString("string", "7");
|
|
42
|
+
|
|
43
|
+
assertEquals(7, BundleValueReader.getIntPreserving(bundle, "integer"));
|
|
44
|
+
assertEquals(7, BundleValueReader.getIntPreserving(bundle, "double"));
|
|
45
|
+
assertEquals(0, BundleValueReader.getIntPreserving(bundle, "missing"));
|
|
46
|
+
assertEquals(0, BundleValueReader.getIntPreserving(bundle, "explicitNull"));
|
|
47
|
+
|
|
48
|
+
assertThrows(
|
|
49
|
+
ClassCastException.class, () -> BundleValueReader.getIntPreserving(bundle, "long"));
|
|
50
|
+
assertThrows(
|
|
51
|
+
ClassCastException.class, () -> BundleValueReader.getIntPreserving(bundle, "float"));
|
|
52
|
+
assertThrows(
|
|
53
|
+
ClassCastException.class, () -> BundleValueReader.getIntPreserving(bundle, "string"));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Test
|
|
57
|
+
public void getIntPreserving_withDefault_distinguishesMissingFromExplicitNull() {
|
|
58
|
+
Bundle bundle = new Bundle();
|
|
59
|
+
bundle.putString("explicitNull", null);
|
|
60
|
+
bundle.putLong("long", 7L);
|
|
61
|
+
|
|
62
|
+
assertEquals(42, BundleValueReader.getIntPreserving(bundle, "missing", 42));
|
|
63
|
+
assertEquals(0, BundleValueReader.getIntPreserving(bundle, "explicitNull", 42));
|
|
64
|
+
assertThrows(
|
|
65
|
+
ClassCastException.class, () -> BundleValueReader.getIntPreserving(bundle, "long", 42));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Test
|
|
69
|
+
public void getLongPreserving_matchesCurrentObjectUtilsBehavior() {
|
|
70
|
+
Bundle bundle = new Bundle();
|
|
71
|
+
bundle.putLong("long", 9000000000L);
|
|
72
|
+
bundle.putDouble("double", 7.9d);
|
|
73
|
+
bundle.putString("explicitNull", null);
|
|
74
|
+
bundle.putInt("integer", 7);
|
|
75
|
+
bundle.putFloat("float", 7.5f);
|
|
76
|
+
bundle.putString("string", "7");
|
|
77
|
+
|
|
78
|
+
assertEquals(9000000000L, BundleValueReader.getLongPreserving(bundle, "long"));
|
|
79
|
+
assertEquals(7L, BundleValueReader.getLongPreserving(bundle, "double"));
|
|
80
|
+
|
|
81
|
+
assertThrows(
|
|
82
|
+
NullPointerException.class, () -> BundleValueReader.getLongPreserving(bundle, "missing"));
|
|
83
|
+
assertThrows(
|
|
84
|
+
NullPointerException.class,
|
|
85
|
+
() -> BundleValueReader.getLongPreserving(bundle, "explicitNull"));
|
|
86
|
+
assertThrows(
|
|
87
|
+
ClassCastException.class, () -> BundleValueReader.getLongPreserving(bundle, "integer"));
|
|
88
|
+
assertThrows(
|
|
89
|
+
ClassCastException.class, () -> BundleValueReader.getLongPreserving(bundle, "float"));
|
|
90
|
+
assertThrows(
|
|
91
|
+
ClassCastException.class, () -> BundleValueReader.getLongPreserving(bundle, "string"));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@Test
|
|
95
|
+
public void getLongPreserving_withDefault_distinguishesMissingFromExplicitNull() {
|
|
96
|
+
Bundle bundle = new Bundle();
|
|
97
|
+
bundle.putString("explicitNull", null);
|
|
98
|
+
bundle.putInt("integer", 7);
|
|
99
|
+
|
|
100
|
+
assertEquals(42L, BundleValueReader.getLongPreserving(bundle, "missing", 42L));
|
|
101
|
+
assertThrows(
|
|
102
|
+
NullPointerException.class,
|
|
103
|
+
() -> BundleValueReader.getLongPreserving(bundle, "explicitNull", 42L));
|
|
104
|
+
assertThrows(
|
|
105
|
+
ClassCastException.class, () -> BundleValueReader.getLongPreserving(bundle, "integer", 42L));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Test
|
|
109
|
+
public void getArrayListValue_returnsRawArrayListAndNullForMissingAndExplicitNull() {
|
|
110
|
+
ArrayList<String> values = new ArrayList<>();
|
|
111
|
+
values.add("one");
|
|
112
|
+
values.add("two");
|
|
113
|
+
|
|
114
|
+
Bundle bundle = new Bundle();
|
|
115
|
+
bundle.putStringArrayList("values", values);
|
|
116
|
+
bundle.putStringArrayList("explicitNull", null);
|
|
117
|
+
|
|
118
|
+
assertSame(values, BundleValueReader.getArrayListValue(bundle, "values"));
|
|
119
|
+
assertNull(BundleValueReader.getArrayListValue(bundle, "missing"));
|
|
120
|
+
assertNull(BundleValueReader.getArrayListValue(bundle, "explicitNull"));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@Test
|
|
124
|
+
public void getArrayListValue_preservesTopLevelCastFailure() {
|
|
125
|
+
Bundle bundle = new Bundle();
|
|
126
|
+
bundle.putString("wrongType", "value");
|
|
127
|
+
|
|
128
|
+
assertThrows(
|
|
129
|
+
ClassCastException.class, () -> BundleValueReader.getArrayListValue(bundle, "wrongType"));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
package app.notifee.core.utility;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertNull;
|
|
5
|
+
import static org.junit.Assert.assertThrows;
|
|
6
|
+
import static org.junit.Assert.assertTrue;
|
|
7
|
+
|
|
8
|
+
import android.os.Bundle;
|
|
9
|
+
import java.util.ArrayList;
|
|
10
|
+
import java.util.Arrays;
|
|
11
|
+
import java.util.Map;
|
|
12
|
+
import org.junit.Test;
|
|
13
|
+
import org.junit.runner.RunWith;
|
|
14
|
+
import org.robolectric.RobolectricTestRunner;
|
|
15
|
+
|
|
16
|
+
@RunWith(RobolectricTestRunner.class)
|
|
17
|
+
public class ObjectUtilsTest {
|
|
18
|
+
|
|
19
|
+
@Test
|
|
20
|
+
public void getInt_preservesCurrentCoercionAndFragility() {
|
|
21
|
+
assertEquals(7, ObjectUtils.getInt(Integer.valueOf(7)));
|
|
22
|
+
assertEquals(7, ObjectUtils.getInt(Double.valueOf(7.9d)));
|
|
23
|
+
assertEquals(0, ObjectUtils.getInt(null));
|
|
24
|
+
|
|
25
|
+
assertThrows(ClassCastException.class, () -> ObjectUtils.getInt(Long.valueOf(7L)));
|
|
26
|
+
assertThrows(ClassCastException.class, () -> ObjectUtils.getInt(Float.valueOf(7.5f)));
|
|
27
|
+
assertThrows(ClassCastException.class, () -> ObjectUtils.getInt("7"));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Test
|
|
31
|
+
public void getLong_preservesCurrentCoercionAndFragility() {
|
|
32
|
+
assertEquals(9000000000L, ObjectUtils.getLong(Long.valueOf(9000000000L)));
|
|
33
|
+
assertEquals(7L, ObjectUtils.getLong(Double.valueOf(7.9d)));
|
|
34
|
+
|
|
35
|
+
assertThrows(ClassCastException.class, () -> ObjectUtils.getLong(Integer.valueOf(7)));
|
|
36
|
+
assertThrows(ClassCastException.class, () -> ObjectUtils.getLong(Float.valueOf(7.5f)));
|
|
37
|
+
assertThrows(ClassCastException.class, () -> ObjectUtils.getLong("7"));
|
|
38
|
+
assertThrows(NullPointerException.class, () -> ObjectUtils.getLong(null));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Test
|
|
42
|
+
public void bundleToMap_preservesNestedBundlesListsArraysAndNullValues() {
|
|
43
|
+
Bundle nested = new Bundle();
|
|
44
|
+
nested.putString("name", "nested");
|
|
45
|
+
nested.putInt("count", 3);
|
|
46
|
+
|
|
47
|
+
ArrayList<Object> nestedList = new ArrayList<>();
|
|
48
|
+
nestedList.add("item");
|
|
49
|
+
nestedList.add(4);
|
|
50
|
+
nestedList.add(nested);
|
|
51
|
+
|
|
52
|
+
Bundle bundle = new Bundle();
|
|
53
|
+
bundle.putString("string", "value");
|
|
54
|
+
bundle.putString("nullString", null);
|
|
55
|
+
bundle.putInt("integer", 5);
|
|
56
|
+
bundle.putLong("long", 6L);
|
|
57
|
+
bundle.putDouble("double", 7.5d);
|
|
58
|
+
bundle.putBoolean("boolean", true);
|
|
59
|
+
bundle.putBundle("nestedBundle", nested);
|
|
60
|
+
bundle.putIntArray("intArray", new int[] {1, 2});
|
|
61
|
+
bundle.putDoubleArray("doubleArray", new double[] {1.25d, 2.5d});
|
|
62
|
+
bundle.putBooleanArray("booleanArray", new boolean[] {true, false});
|
|
63
|
+
bundle.putStringArray("stringArray", new String[] {"a", "b"});
|
|
64
|
+
putRawParcelableArrayList(bundle, "nestedList", nestedList);
|
|
65
|
+
|
|
66
|
+
Map<String, Object> map = ObjectUtils.bundleToMap(bundle);
|
|
67
|
+
|
|
68
|
+
assertEquals("value", map.get("string"));
|
|
69
|
+
assertTrue(map.containsKey("nullString"));
|
|
70
|
+
assertNull(map.get("nullString"));
|
|
71
|
+
assertEquals(5, map.get("integer"));
|
|
72
|
+
assertEquals(6L, map.get("long"));
|
|
73
|
+
assertEquals(7.5d, map.get("double"));
|
|
74
|
+
assertEquals(true, map.get("boolean"));
|
|
75
|
+
assertEquals(Arrays.asList(1, 2), map.get("intArray"));
|
|
76
|
+
assertEquals(Arrays.asList(1.25d, 2.5d), map.get("doubleArray"));
|
|
77
|
+
assertEquals(Arrays.asList(true, false), map.get("booleanArray"));
|
|
78
|
+
assertEquals(Arrays.asList("a", "b"), map.get("stringArray"));
|
|
79
|
+
|
|
80
|
+
Map<?, ?> nestedMap = (Map<?, ?>) map.get("nestedBundle");
|
|
81
|
+
assertEquals("nested", nestedMap.get("name"));
|
|
82
|
+
assertEquals(3, nestedMap.get("count"));
|
|
83
|
+
|
|
84
|
+
ArrayList<?> convertedList = (ArrayList<?>) map.get("nestedList");
|
|
85
|
+
assertEquals("item", convertedList.get(0));
|
|
86
|
+
assertEquals(4, convertedList.get(1));
|
|
87
|
+
assertEquals("nested", ((Map<?, ?>) convertedList.get(2)).get("name"));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@Test
|
|
91
|
+
public void listToMap_preservesRecursiveConversionAndNumberRules() {
|
|
92
|
+
Bundle nested = new Bundle();
|
|
93
|
+
nested.putString("name", "nested");
|
|
94
|
+
|
|
95
|
+
ArrayList<Object> innerList = new ArrayList<>();
|
|
96
|
+
innerList.add("inner");
|
|
97
|
+
innerList.add(2L);
|
|
98
|
+
|
|
99
|
+
ArrayList<Object> list = new ArrayList<>();
|
|
100
|
+
list.add(null);
|
|
101
|
+
list.add("text");
|
|
102
|
+
list.add(1);
|
|
103
|
+
list.add(2L);
|
|
104
|
+
list.add(3.5f);
|
|
105
|
+
list.add(true);
|
|
106
|
+
list.add(nested);
|
|
107
|
+
list.add(new int[] {4, 5});
|
|
108
|
+
list.add(innerList);
|
|
109
|
+
|
|
110
|
+
ArrayList<Object> converted = ObjectUtils.listToMap(list);
|
|
111
|
+
|
|
112
|
+
assertNull(converted.get(0));
|
|
113
|
+
assertEquals("text", converted.get(1));
|
|
114
|
+
assertEquals(1, converted.get(2));
|
|
115
|
+
assertEquals(2.0d, converted.get(3));
|
|
116
|
+
assertEquals(3.5d, converted.get(4));
|
|
117
|
+
assertEquals(true, converted.get(5));
|
|
118
|
+
assertEquals("nested", ((Map<?, ?>) converted.get(6)).get("name"));
|
|
119
|
+
assertEquals(Arrays.asList(4, 5), converted.get(7));
|
|
120
|
+
|
|
121
|
+
ArrayList<?> convertedInnerList = (ArrayList<?>) converted.get(8);
|
|
122
|
+
assertEquals("inner", convertedInnerList.get(0));
|
|
123
|
+
assertEquals(2.0d, convertedInnerList.get(1));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@Test
|
|
127
|
+
public void bundleAndListConversion_throwForUnsupportedValueTypes() {
|
|
128
|
+
Bundle bundle = new Bundle();
|
|
129
|
+
bundle.putCharArray("unsupportedArray", new char[] {'a'});
|
|
130
|
+
assertThrows(IllegalArgumentException.class, () -> ObjectUtils.bundleToMap(bundle));
|
|
131
|
+
|
|
132
|
+
ArrayList<Object> list = new ArrayList<>();
|
|
133
|
+
list.add(new Object());
|
|
134
|
+
assertThrows(IllegalArgumentException.class, () -> ObjectUtils.listToMap(list));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
138
|
+
private static void putRawParcelableArrayList(
|
|
139
|
+
Bundle bundle, String key, ArrayList<?> arrayList) {
|
|
140
|
+
bundle.putParcelableArrayList(key, (ArrayList) arrayList);
|
|
141
|
+
}
|
|
142
|
+
}
|