From d0ac2c9d1af11465c39e0a24b33d1981fdce9996 Mon Sep 17 00:00:00 2001 From: Mihai-Cristian Condrea Date: Tue, 16 Sep 2025 21:19:09 +0300 Subject: [PATCH] Handle invalid monospace font preferences --- .../java/utils/FontManager.java | 56 ++++++++++++---- .../java/utils/FontManagerTest.java | 64 ++++++++++++++++++- 2 files changed, 105 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/utils/FontManager.java b/app/src/main/java/com/d4rk/androidtutorials/java/utils/FontManager.java index e264a702..3b43c6bf 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/utils/FontManager.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/utils/FontManager.java @@ -10,26 +10,56 @@ public class FontManager { + private static final String DEFAULT_FONT_CODE = "6"; + public static Typeface getMonospaceFont(Context context, SharedPreferences prefs) { String key = context.getString(R.string.key_monospace_font); String font; + boolean resetPreference = false; try { - font = prefs.getString(key, "6"); + font = prefs.getString(key, DEFAULT_FONT_CODE); } catch (ClassCastException e) { - prefs.edit().remove(key).apply(); - font = "6"; + font = DEFAULT_FONT_CODE; + resetPreference = true; } if (font == null) { - font = "6"; + font = DEFAULT_FONT_CODE; + resetPreference = true; + } + + Typeface typeface; + switch (font) { + case "0": + typeface = ResourcesCompat.getFont(context, R.font.font_audiowide); + break; + case "1": + typeface = ResourcesCompat.getFont(context, R.font.font_fira_code); + break; + case "2": + typeface = ResourcesCompat.getFont(context, R.font.font_jetbrains_mono); + break; + case "3": + typeface = ResourcesCompat.getFont(context, R.font.font_noto_sans_mono); + break; + case "4": + typeface = ResourcesCompat.getFont(context, R.font.font_poppins); + break; + case "5": + typeface = ResourcesCompat.getFont(context, R.font.font_roboto_mono); + break; + case DEFAULT_FONT_CODE: + typeface = ResourcesCompat.getFont(context, R.font.font_google_sans_code); + break; + default: + typeface = ResourcesCompat.getFont(context, R.font.font_google_sans_code); + resetPreference = true; + break; } - return switch (font) { - case "0" -> ResourcesCompat.getFont(context, R.font.font_audiowide); - case "1" -> ResourcesCompat.getFont(context, R.font.font_fira_code); - case "2" -> ResourcesCompat.getFont(context, R.font.font_jetbrains_mono); - case "3" -> ResourcesCompat.getFont(context, R.font.font_noto_sans_mono); - case "4" -> ResourcesCompat.getFont(context, R.font.font_poppins); - case "5" -> ResourcesCompat.getFont(context, R.font.font_roboto_mono); - default -> ResourcesCompat.getFont(context, R.font.font_google_sans_code); - }; + + if (resetPreference) { + prefs.edit().remove(key).apply(); + } + + return typeface; } } diff --git a/app/src/test/java/com/d4rk/androidtutorials/java/utils/FontManagerTest.java b/app/src/test/java/com/d4rk/androidtutorials/java/utils/FontManagerTest.java index 458e4cba..eb0327fc 100644 --- a/app/src/test/java/com/d4rk/androidtutorials/java/utils/FontManagerTest.java +++ b/app/src/test/java/com/d4rk/androidtutorials/java/utils/FontManagerTest.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertSame; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -25,7 +26,7 @@ public class FontManagerTest { @Test - public void getMonospaceFont_returnsExpectedTypefaceForStoredValues() { + public void getMonospaceFont_returnsExpectedTypefaceForValidCodes() { Context context = mock(Context.class); when(context.getString(R.string.key_monospace_font)).thenReturn("monospace_font"); @@ -51,13 +52,72 @@ public void getMonospaceFont_returnsExpectedTypefaceForStoredValues() { assertSame("Unexpected typeface for value " + entry.getKey(), expectedTypeface, result); verify(prefs).getString("monospace_font", "6"); + verify(prefs, never()).edit(); resourcesStatic.verify(() -> ResourcesCompat.getFont(context, entry.getValue())); } } } @Test - public void getMonospaceFont_removesInvalidPreferenceValueAndReturnsDefaultFont() { + public void getMonospaceFont_resetsPreferenceWhenCodeIsInvalid() { + Context context = mock(Context.class); + SharedPreferences prefs = mock(SharedPreferences.class); + SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); + + when(context.getString(R.string.key_monospace_font)).thenReturn("monospace_font"); + when(prefs.edit()).thenReturn(editor); + when(editor.remove("monospace_font")).thenReturn(editor); + when(prefs.getString("monospace_font", "6")).thenReturn("invalid"); + + Typeface defaultTypeface = mock(Typeface.class); + + try (MockedStatic resourcesStatic = Mockito.mockStatic(ResourcesCompat.class)) { + resourcesStatic.when(() -> ResourcesCompat.getFont(context, R.font.font_google_sans_code)) + .thenReturn(defaultTypeface); + + Typeface result = FontManager.getMonospaceFont(context, prefs); + + assertSame(defaultTypeface, result); + verify(prefs).getString("monospace_font", "6"); + verify(prefs).edit(); + InOrder inOrder = inOrder(editor); + inOrder.verify(editor).remove("monospace_font"); + inOrder.verify(editor).apply(); + resourcesStatic.verify(() -> ResourcesCompat.getFont(context, R.font.font_google_sans_code)); + } + } + + @Test + public void getMonospaceFont_resetsPreferenceWhenCodeIsMissing() { + Context context = mock(Context.class); + SharedPreferences prefs = mock(SharedPreferences.class); + SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class); + + when(context.getString(R.string.key_monospace_font)).thenReturn("monospace_font"); + when(prefs.edit()).thenReturn(editor); + when(editor.remove("monospace_font")).thenReturn(editor); + when(prefs.getString("monospace_font", "6")).thenReturn(null); + + Typeface defaultTypeface = mock(Typeface.class); + + try (MockedStatic resourcesStatic = Mockito.mockStatic(ResourcesCompat.class)) { + resourcesStatic.when(() -> ResourcesCompat.getFont(context, R.font.font_google_sans_code)) + .thenReturn(defaultTypeface); + + Typeface result = FontManager.getMonospaceFont(context, prefs); + + assertSame(defaultTypeface, result); + verify(prefs).getString("monospace_font", "6"); + verify(prefs).edit(); + InOrder inOrder = inOrder(editor); + inOrder.verify(editor).remove("monospace_font"); + inOrder.verify(editor).apply(); + resourcesStatic.verify(() -> ResourcesCompat.getFont(context, R.font.font_google_sans_code)); + } + } + + @Test + public void getMonospaceFont_resetsPreferenceWhenValueHasWrongType() { Context context = mock(Context.class); SharedPreferences prefs = mock(SharedPreferences.class); SharedPreferences.Editor editor = mock(SharedPreferences.Editor.class);