From 49919622d8878b3ab3446ba9efefd363c7b77936 Mon Sep 17 00:00:00 2001 From: Mihai-Cristian Condrea Date: Sun, 14 Sep 2025 11:21:16 +0300 Subject: [PATCH] test: add MainViewModel tests --- .../ui/screens/main/MainViewModelTest.java | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 app/src/test/java/com/d4rk/androidtutorials/java/ui/screens/main/MainViewModelTest.java diff --git a/app/src/test/java/com/d4rk/androidtutorials/java/ui/screens/main/MainViewModelTest.java b/app/src/test/java/com/d4rk/androidtutorials/java/ui/screens/main/MainViewModelTest.java new file mode 100644 index 00000000..fd66b9ba --- /dev/null +++ b/app/src/test/java/com/d4rk/androidtutorials/java/ui/screens/main/MainViewModelTest.java @@ -0,0 +1,173 @@ +package com.d4rk.androidtutorials.java.ui.screens.main; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import androidx.arch.core.executor.testing.InstantTaskExecutorRule; + +import com.d4rk.androidtutorials.java.R; +import com.d4rk.androidtutorials.java.domain.main.ApplyLanguageSettingsUseCase; +import com.d4rk.androidtutorials.java.domain.main.ApplyThemeSettingsUseCase; +import com.d4rk.androidtutorials.java.domain.main.GetAppUpdateManagerUseCase; +import com.d4rk.androidtutorials.java.domain.main.GetBottomNavLabelVisibilityUseCase; +import com.d4rk.androidtutorials.java.domain.main.GetDefaultTabPreferenceUseCase; +import com.d4rk.androidtutorials.java.domain.main.MarkStartupScreenShownUseCase; +import com.d4rk.androidtutorials.java.domain.main.ShouldShowStartupScreenUseCase; +import com.google.android.material.navigation.NavigationBarView; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.Mockito; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public class MainViewModelTest { + + @Rule + public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule(); + + private ApplyThemeSettingsUseCase applyThemeSettingsUseCase; + private GetBottomNavLabelVisibilityUseCase getBottomNavLabelVisibilityUseCase; + private GetDefaultTabPreferenceUseCase getDefaultTabPreferenceUseCase; + private ApplyLanguageSettingsUseCase applyLanguageSettingsUseCase; + private ShouldShowStartupScreenUseCase shouldShowStartupScreenUseCase; + private MarkStartupScreenShownUseCase markStartupScreenShownUseCase; + private GetAppUpdateManagerUseCase getAppUpdateManagerUseCase; + + private final String[] themeValues = {"MODE_NIGHT_FOLLOW_SYSTEM", "MODE_NIGHT_NO", "MODE_NIGHT_YES"}; + private final String[] bottomNavBarLabelsValues = {"labeled", "selected", "unlabeled"}; + private final String[] defaultTabValues = {"home", "android_studio", "about"}; + + @Before + public void setUp() { + applyThemeSettingsUseCase = Mockito.mock(ApplyThemeSettingsUseCase.class); + getBottomNavLabelVisibilityUseCase = Mockito.mock(GetBottomNavLabelVisibilityUseCase.class); + getDefaultTabPreferenceUseCase = Mockito.mock(GetDefaultTabPreferenceUseCase.class); + applyLanguageSettingsUseCase = Mockito.mock(ApplyLanguageSettingsUseCase.class); + shouldShowStartupScreenUseCase = Mockito.mock(ShouldShowStartupScreenUseCase.class); + markStartupScreenShownUseCase = Mockito.mock(MarkStartupScreenShownUseCase.class); + getAppUpdateManagerUseCase = Mockito.mock(GetAppUpdateManagerUseCase.class); + } + + @Test + public void applySettingsUpdatesUiStateForLabeledHome() { + Mockito.when(applyThemeSettingsUseCase.invoke(themeValues)).thenReturn(true); + Mockito.when(getBottomNavLabelVisibilityUseCase.invoke()).thenReturn("labeled"); + Mockito.when(getDefaultTabPreferenceUseCase.invoke()).thenReturn("home"); + + MainViewModel viewModel = new MainViewModel( + applyThemeSettingsUseCase, + getBottomNavLabelVisibilityUseCase, + getDefaultTabPreferenceUseCase, + applyLanguageSettingsUseCase, + shouldShowStartupScreenUseCase, + markStartupScreenShownUseCase, + getAppUpdateManagerUseCase + ); + + List loading = new ArrayList<>(); + viewModel.getLoadingState().observeForever(loading::add); + + viewModel.applySettings(themeValues, bottomNavBarLabelsValues, defaultTabValues); + + assertEquals(List.of(false, true, false), loading); + + MainUiState state = viewModel.getUiState().getValue(); + assertNotNull(state); + assertEquals(NavigationBarView.LABEL_VISIBILITY_LABELED, state.bottomNavVisibility()); + assertEquals(R.id.navigation_home, state.defaultNavDestination()); + assertTrue(state.themeChanged()); + } + + @Test + public void applySettingsUpdatesUiStateForSelectedAndroidStudio() { + Mockito.when(applyThemeSettingsUseCase.invoke(themeValues)).thenReturn(false); + Mockito.when(getBottomNavLabelVisibilityUseCase.invoke()).thenReturn("selected"); + Mockito.when(getDefaultTabPreferenceUseCase.invoke()).thenReturn("android_studio"); + + MainViewModel viewModel = new MainViewModel( + applyThemeSettingsUseCase, + getBottomNavLabelVisibilityUseCase, + getDefaultTabPreferenceUseCase, + applyLanguageSettingsUseCase, + shouldShowStartupScreenUseCase, + markStartupScreenShownUseCase, + getAppUpdateManagerUseCase + ); + + List loading = new ArrayList<>(); + viewModel.getLoadingState().observeForever(loading::add); + + viewModel.applySettings(themeValues, bottomNavBarLabelsValues, defaultTabValues); + + assertEquals(List.of(false, true, false), loading); + + MainUiState state = viewModel.getUiState().getValue(); + assertNotNull(state); + assertEquals(NavigationBarView.LABEL_VISIBILITY_SELECTED, state.bottomNavVisibility()); + assertEquals(R.id.navigation_android_studio, state.defaultNavDestination()); + assertTrue(!state.themeChanged()); + } + + @Test + public void applySettingsUpdatesUiStateForUnlabeledAbout() { + Mockito.when(applyThemeSettingsUseCase.invoke(themeValues)).thenReturn(true); + Mockito.when(getBottomNavLabelVisibilityUseCase.invoke()).thenReturn("unlabeled"); + Mockito.when(getDefaultTabPreferenceUseCase.invoke()).thenReturn("about"); + + MainViewModel viewModel = new MainViewModel( + applyThemeSettingsUseCase, + getBottomNavLabelVisibilityUseCase, + getDefaultTabPreferenceUseCase, + applyLanguageSettingsUseCase, + shouldShowStartupScreenUseCase, + markStartupScreenShownUseCase, + getAppUpdateManagerUseCase + ); + + List loading = new ArrayList<>(); + viewModel.getLoadingState().observeForever(loading::add); + + viewModel.applySettings(themeValues, bottomNavBarLabelsValues, defaultTabValues); + + assertEquals(List.of(false, true, false), loading); + + MainUiState state = viewModel.getUiState().getValue(); + assertNotNull(state); + assertEquals(NavigationBarView.LABEL_VISIBILITY_UNLABELED, state.bottomNavVisibility()); + assertEquals(R.id.navigation_about, state.defaultNavDestination()); + assertTrue(state.themeChanged()); + } + + private int callVisibilityMode(String value) throws Exception { + Method method = MainViewModel.class.getDeclaredMethod( + "getVisibilityMode", String.class, String[].class); + method.setAccessible(true); + return (Integer) method.invoke(null, value, bottomNavBarLabelsValues); + } + + @Test + public void getVisibilityModeReturnsLabeled() throws Exception { + assertEquals(NavigationBarView.LABEL_VISIBILITY_LABELED, callVisibilityMode("labeled")); + } + + @Test + public void getVisibilityModeReturnsSelected() throws Exception { + assertEquals(NavigationBarView.LABEL_VISIBILITY_SELECTED, callVisibilityMode("selected")); + } + + @Test + public void getVisibilityModeReturnsUnlabeled() throws Exception { + assertEquals(NavigationBarView.LABEL_VISIBILITY_UNLABELED, callVisibilityMode("unlabeled")); + } + + @Test + public void getVisibilityModeReturnsAutoForUnknown() throws Exception { + assertEquals(NavigationBarView.LABEL_VISIBILITY_AUTO, callVisibilityMode("other")); + } +} +