44import android .app .NotificationManager ;
55import android .app .PendingIntent ;
66import android .content .Context ;
7+ import android .content .pm .ApplicationInfo ;
8+ import android .content .pm .PackageManager ;
9+ import android .content .res .Resources ;
710import android .os .Build ;
811import android .os .Bundle ;
912import android .service .notification .StatusBarNotification ;
2932
3033import static org .robolectric .Shadows .shadowOf ;
3134
35+ import static org .mockito .Mockito .spy ;
36+ import static org .mockito .Mockito .when ;
37+
3238import org .json .JSONArray ;
3339import org .json .JSONObject ;
3440
@@ -241,4 +247,98 @@ public void testPendingIntentFlags() throws Exception {
241247 assertTrue ((textInputFlags & PendingIntent .FLAG_UPDATE_CURRENT ) != 0 );
242248 assertTrue ((textInputFlags & PendingIntent .FLAG_MUTABLE ) != 0 ); // Should be mutable for text input
243249 }
250+
251+ @ Test
252+ public void testIconFallbackToAppIcon () throws Exception {
253+ Context context = iconTestContext (new Bundle (), null , 0 , android .R .drawable .sym_def_app_icon );
254+
255+ assertEquals (android .R .drawable .sym_def_app_icon , IterableNotificationHelper .getIconId (context ));
256+ }
257+
258+ @ Test
259+ public void testIconUsesIterableMetadata () throws Exception {
260+ Bundle metaData = new Bundle ();
261+ metaData .putInt (IterableConstants .NOTIFICATION_ICON_NAME , android .R .drawable .ic_dialog_email );
262+ Context context = iconTestContext (metaData , null , 0 , android .R .drawable .sym_def_app_icon );
263+
264+ assertEquals (android .R .drawable .ic_dialog_email , IterableNotificationHelper .getIconId (context ));
265+ }
266+
267+ @ Test
268+ public void testIconFallbackToFirebaseMetadata () throws Exception {
269+ Bundle metaData = new Bundle ();
270+ metaData .putInt (IterableConstants .FIREBASE_NOTIFICATION_ICON_KEY , android .R .drawable .ic_dialog_info );
271+ Context context = iconTestContext (metaData , null , 0 , android .R .drawable .sym_def_app_icon );
272+
273+ assertEquals (android .R .drawable .ic_dialog_info , IterableNotificationHelper .getIconId (context ));
274+ }
275+
276+ @ Test
277+ public void testIconIterableMetadataTakesPriorityOverFirebase () throws Exception {
278+ Bundle metaData = new Bundle ();
279+ metaData .putInt (IterableConstants .NOTIFICATION_ICON_NAME , android .R .drawable .ic_dialog_alert );
280+ metaData .putInt (IterableConstants .FIREBASE_NOTIFICATION_ICON_KEY , android .R .drawable .ic_dialog_info );
281+ Context context = iconTestContext (metaData , null , 0 , android .R .drawable .sym_def_app_icon );
282+
283+ assertEquals (android .R .drawable .ic_dialog_alert , IterableNotificationHelper .getIconId (context ));
284+ }
285+
286+ @ Test
287+ public void testIconFallbackToNotificationIconDrawable () throws Exception {
288+ Context context = iconTestContext (new Bundle (),
289+ IterableConstants .NOTIFICATION_ICON_DRAWABLE_NOTIFICATION_ICON , android .R .drawable .ic_menu_info_details ,
290+ android .R .drawable .sym_def_app_icon );
291+
292+ assertEquals (android .R .drawable .ic_menu_info_details , IterableNotificationHelper .getIconId (context ));
293+ }
294+
295+ @ Test
296+ public void testIconFallbackToIcNotificationDrawable () throws Exception {
297+ Context context = iconTestContext (new Bundle (),
298+ IterableConstants .NOTIFICATION_ICON_DRAWABLE_IC_NOTIFICATION , android .R .drawable .ic_menu_help ,
299+ android .R .drawable .sym_def_app_icon );
300+
301+ assertEquals (android .R .drawable .ic_menu_help , IterableNotificationHelper .getIconId (context ));
302+ }
303+
304+ @ Test
305+ public void testIconFirebaseMetadataTakesPriorityOverDrawable () throws Exception {
306+ Bundle metaData = new Bundle ();
307+ metaData .putInt (IterableConstants .FIREBASE_NOTIFICATION_ICON_KEY , android .R .drawable .ic_dialog_info );
308+ Context context = iconTestContext (metaData ,
309+ IterableConstants .NOTIFICATION_ICON_DRAWABLE_NOTIFICATION_ICON , android .R .drawable .ic_menu_info_details ,
310+ android .R .drawable .sym_def_app_icon );
311+
312+ assertEquals (android .R .drawable .ic_dialog_info , IterableNotificationHelper .getIconId (context ));
313+ }
314+
315+ /**
316+ * Builds a context spy with fully controlled icon inputs: the application meta-data bundle, an
317+ * optional drawable name resolvable via {@link Resources#getIdentifier}, and the launcher icon.
318+ * Lets each fallback tier of {@link IterableNotificationHelper#getIconId} be exercised in
319+ * isolation without mutating shared Robolectric state.
320+ */
321+ private Context iconTestContext (Bundle metaData , String drawableName , int drawableResId , int appIcon ) throws Exception {
322+ Context context = spy (getContext ());
323+
324+ ApplicationInfo appInfo = new ApplicationInfo ();
325+ appInfo .packageName = getContext ().getPackageName ();
326+ appInfo .metaData = metaData ;
327+ appInfo .icon = appIcon ;
328+
329+ PackageManager packageManager = spy (getContext ().getPackageManager ());
330+ when (packageManager .getApplicationInfo (getContext ().getPackageName (), PackageManager .GET_META_DATA ))
331+ .thenReturn (appInfo );
332+ when (context .getPackageManager ()).thenReturn (packageManager );
333+ when (context .getApplicationInfo ()).thenReturn (appInfo );
334+
335+ if (drawableName != null ) {
336+ Resources resources = spy (getContext ().getResources ());
337+ when (resources .getIdentifier (drawableName , IterableConstants .ICON_FOLDER_IDENTIFIER , getContext ().getPackageName ()))
338+ .thenReturn (drawableResId );
339+ when (context .getResources ()).thenReturn (resources );
340+ }
341+
342+ return context ;
343+ }
244344}
0 commit comments