From bcbdf18d9ccfa24cf6d71bfe079302b640e27f29 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Fri, 21 Jul 2023 19:16:29 +0530 Subject: [PATCH 1/8] Network module integration --- .../java/foundation/e/apps/di/LoginModule.kt | 10 +++++ .../login/repository/LoginRepository.kt | 13 ++++++ .../login/repository/LoginRepositoryImpl.kt | 18 ++++++++ .../domain/login/usecase/UserLoginUseCase.kt | 37 +++++++++++++++++ .../e/apps/presentation/login/LoginState.kt | 8 ++++ .../login/LoginViewModel.kt | 41 ++++++++++++++++++- .../java/foundation/e/apps/ui/MainActivity.kt | 4 +- .../apps/ui/parentFragment/TimeoutFragment.kt | 2 +- .../e/apps/ui/settings/SettingsFragment.kt | 2 +- .../e/apps/ui/setup/signin/SignInFragment.kt | 2 +- .../signin/google/GoogleSignInFragment.kt | 2 +- .../java/foundation/e/apps/utils/Resource.kt | 8 ++++ 12 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt create mode 100644 app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt create mode 100644 app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt create mode 100644 app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt rename app/src/main/java/foundation/e/apps/{data => presentation}/login/LoginViewModel.kt (76%) create mode 100644 app/src/main/java/foundation/e/apps/utils/Resource.kt diff --git a/app/src/main/java/foundation/e/apps/di/LoginModule.kt b/app/src/main/java/foundation/e/apps/di/LoginModule.kt index f59a084b8..9708c9a8e 100644 --- a/app/src/main/java/foundation/e/apps/di/LoginModule.kt +++ b/app/src/main/java/foundation/e/apps/di/LoginModule.kt @@ -24,6 +24,8 @@ import dagger.hilt.components.SingletonComponent import foundation.e.apps.data.login.LoginSourceCleanApk import foundation.e.apps.data.login.LoginSourceGPlay import foundation.e.apps.data.login.LoginSourceInterface +import foundation.e.apps.domain.login.repository.LoginRepositoryImpl +import foundation.e.apps.domain.login.usecase.UserLoginUseCase @InstallIn(SingletonComponent::class) @Module @@ -36,4 +38,12 @@ object LoginModule { ): List { return listOf(gPlay, cleanApk) } + + @Provides + fun provideLoginUserCase( + loginRepositoryImpl: LoginRepositoryImpl + ): UserLoginUseCase { + return UserLoginUseCase(loginRepositoryImpl) + } + } diff --git a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt new file mode 100644 index 000000000..a35c1bc98 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt @@ -0,0 +1,13 @@ +package foundation.e.apps.domain.login.repository + +import app.lounge.model.AnonymousAuthDataRequestBody +import app.lounge.model.AuthDataResponse + + +interface LoginRepository { + + suspend fun anonymousUser( + authDataRequestBody: AnonymousAuthDataRequestBody + ): AuthDataResponse + +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt new file mode 100644 index 000000000..4e4b30127 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt @@ -0,0 +1,18 @@ +package foundation.e.apps.domain.login.repository + +import app.lounge.model.AnonymousAuthDataRequestBody +import app.lounge.model.AuthDataResponse +import app.lounge.networking.NetworkFetching +import javax.inject.Inject + +class LoginRepositoryImpl @Inject constructor( + private val networkFetching: NetworkFetching +): LoginRepository { + + override suspend fun anonymousUser(authDataRequestBody: AnonymousAuthDataRequestBody): AuthDataResponse { + return networkFetching.requestAuthData( + anonymousAuthDataRequestBody = authDataRequestBody + ) + } + +} diff --git a/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt new file mode 100644 index 000000000..e2e8b1813 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt @@ -0,0 +1,37 @@ +package foundation.e.apps.domain.login.usecase + +import app.lounge.model.AnonymousAuthDataRequestBody +import app.lounge.model.AuthDataResponse +import foundation.e.apps.domain.login.repository.LoginRepository +import foundation.e.apps.utils.Resource +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flow +import retrofit2.HttpException +import java.io.IOException +import java.util.Properties +import javax.inject.Inject + +class UserLoginUseCase @Inject constructor( + private val loginRepository: LoginRepository, +) { + + operator fun invoke( + properties: Properties, + userAgent: String + ): Flow> = flow { + try { + emit(Resource.Loading()) + val userResponse: AuthDataResponse = loginRepository.anonymousUser( + authDataRequestBody = AnonymousAuthDataRequestBody( + properties = properties, + userAgent = userAgent + ) + ) + emit(Resource.Success(userResponse)) + } catch(e: HttpException) { + emit(Resource.Error(e.localizedMessage ?: "An unexpected error occured")) + } catch(e: IOException) { + emit(Resource.Error("Couldn't reach server. Check your internet connection.")) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt b/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt new file mode 100644 index 000000000..400fb86bc --- /dev/null +++ b/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt @@ -0,0 +1,8 @@ +package foundation.e.apps.presentation.login + + +data class LoginState( + val isLoading: Boolean = false, + val isLoggedIn: Boolean = false, + val error: String = "" +) diff --git a/app/src/main/java/foundation/e/apps/data/login/LoginViewModel.kt b/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt similarity index 76% rename from app/src/main/java/foundation/e/apps/data/login/LoginViewModel.kt rename to app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt index 25c54362e..c209288af 100644 --- a/app/src/main/java/foundation/e/apps/data/login/LoginViewModel.kt +++ b/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt @@ -15,15 +15,24 @@ * along with this program. If not, see . */ -package foundation.e.apps.data.login +package foundation.e.apps.presentation.login +import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import foundation.e.apps.data.enums.User +import foundation.e.apps.data.login.AuthObject +import foundation.e.apps.data.login.LoginSourceRepository +import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.ui.parentFragment.LoadingViewModel +import foundation.e.apps.utils.Resource +import foundation.e.apps.utils.SystemInfoProvider +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import java.util.Properties import javax.inject.Inject /** @@ -33,6 +42,7 @@ import javax.inject.Inject @HiltViewModel class LoginViewModel @Inject constructor( private val loginSourceRepository: LoginSourceRepository, + private val userLoginUseCase: UserLoginUseCase ) : ViewModel() { /** @@ -131,4 +141,33 @@ class LoginViewModel @Inject constructor( authObjects.postValue(listOf()) } } + + + private val _loginState: MutableLiveData = MutableLiveData() + val loginState: LiveData = _loginState + + + fun authenticateAnonymousUser( + properties: Properties, + userAgent: String = SystemInfoProvider.getAppBuildInfo() + ) { + userLoginUseCase( + properties = properties, + userAgent = userAgent + ).onEach { result -> + when (result) { + is Resource.Success -> { + _loginState.value = LoginState(isLoggedIn = true) + } + is Resource.Error -> { + _loginState.value = LoginState( + error = result.message ?: "An unexpected error occured" + ) + } + is Resource.Loading -> { + _loginState.value = LoginState(isLoading = true) + } + } + }.launchIn(viewModelScope) + } } diff --git a/app/src/main/java/foundation/e/apps/ui/MainActivity.kt b/app/src/main/java/foundation/e/apps/ui/MainActivity.kt index a2426b41f..096c4b98f 100644 --- a/app/src/main/java/foundation/e/apps/ui/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/ui/MainActivity.kt @@ -46,7 +46,7 @@ import foundation.e.apps.R import foundation.e.apps.data.enums.Status import foundation.e.apps.data.fusedDownload.models.FusedDownload import foundation.e.apps.data.login.AuthObject -import foundation.e.apps.data.login.LoginViewModel +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.data.login.exceptions.GPlayValidationException import foundation.e.apps.databinding.ActivityMainBinding import foundation.e.apps.install.updates.UpdatesNotifier @@ -68,7 +68,6 @@ import java.util.UUID @AndroidEntryPoint class MainActivity : AppCompatActivity() { - private lateinit var signInViewModel: SignInViewModel private lateinit var loginViewModel: LoginViewModel private lateinit var binding: ActivityMainBinding private val TAG = MainActivity::class.java.simpleName @@ -90,7 +89,6 @@ class MainActivity : AppCompatActivity() { var hasInternet = true viewModel = ViewModelProvider(this)[MainActivityViewModel::class.java] - signInViewModel = ViewModelProvider(this)[SignInViewModel::class.java] loginViewModel = ViewModelProvider(this)[LoginViewModel::class.java] // navOptions and activityNavController for TOS and SignIn Fragments diff --git a/app/src/main/java/foundation/e/apps/ui/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/ui/parentFragment/TimeoutFragment.kt index 5173da6fe..9a7f8eb10 100644 --- a/app/src/main/java/foundation/e/apps/ui/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/parentFragment/TimeoutFragment.kt @@ -34,7 +34,7 @@ import foundation.e.apps.R import foundation.e.apps.data.enums.User import foundation.e.apps.data.login.AuthObject import foundation.e.apps.data.login.LoginSourceGPlay -import foundation.e.apps.data.login.LoginViewModel +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.data.login.exceptions.CleanApkException import foundation.e.apps.data.login.exceptions.GPlayException import foundation.e.apps.data.login.exceptions.GPlayLoginException diff --git a/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt b/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt index d3c507cad..4a717877d 100644 --- a/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt @@ -40,7 +40,7 @@ import foundation.e.apps.BuildConfig import foundation.e.apps.R import foundation.e.apps.data.enums.User import foundation.e.apps.data.fused.UpdatesDao -import foundation.e.apps.data.login.LoginViewModel +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.databinding.CustomPreferenceBinding import foundation.e.apps.install.updates.UpdatesWorkManager import foundation.e.apps.ui.MainActivityViewModel diff --git a/app/src/main/java/foundation/e/apps/ui/setup/signin/SignInFragment.kt b/app/src/main/java/foundation/e/apps/ui/setup/signin/SignInFragment.kt index 213e84148..7ed9eb765 100644 --- a/app/src/main/java/foundation/e/apps/ui/setup/signin/SignInFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/setup/signin/SignInFragment.kt @@ -7,7 +7,7 @@ import androidx.lifecycle.ViewModelProvider import androidx.navigation.findNavController import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.R -import foundation.e.apps.data.login.LoginViewModel +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.databinding.FragmentSignInBinding import foundation.e.apps.di.CommonUtilsModule.safeNavigate import foundation.e.apps.utils.showGoogleSignInAlertDialog diff --git a/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt b/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt index 8dc3081b3..ed964d86c 100644 --- a/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt @@ -32,7 +32,7 @@ import androidx.navigation.findNavController import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.R import foundation.e.apps.data.gplay.utils.AC2DMUtil -import foundation.e.apps.data.login.LoginViewModel +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.databinding.FragmentGoogleSigninBinding import foundation.e.apps.di.CommonUtilsModule.safeNavigate diff --git a/app/src/main/java/foundation/e/apps/utils/Resource.kt b/app/src/main/java/foundation/e/apps/utils/Resource.kt new file mode 100644 index 000000000..f598e91e5 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/utils/Resource.kt @@ -0,0 +1,8 @@ +package foundation.e.apps.utils + + +sealed class Resource(val data: T? = null, val message: String? = null) { + class Success(data: T) : Resource(data) + class Error(message: String, data: T? = null) : Resource(data, message) + class Loading(data: T? = null) : Resource(data) +} -- GitLab From bbc8d6898835fa63187b07ab42fbb6137d8864c3 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Wed, 26 Jul 2023 22:37:40 +0530 Subject: [PATCH 2/8] Added unit test case --- app/build.gradle | 12 ++++ .../login/repository/LoginRepositoryImpl.kt | 10 +++- .../usecase/repository/LoginRepositoryTest.kt | 59 +++++++++++++++++++ .../java/app/lounge/NetworkFetchingAPITest.kt | 4 +- 4 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt diff --git a/app/build.gradle b/app/build.gradle index f0e0d5e26..e6e74159d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -133,6 +133,12 @@ android { kotlin.sourceSets.all { languageSettings.optIn("kotlin.RequiresOptIn") } + + testOptions { + unitTests { + includeAndroidResources = true + } + } } kapt { @@ -164,6 +170,7 @@ dependencies { implementation "androidx.datastore:datastore-preferences:1.0.0" implementation 'com.facebook.shimmer:shimmer:0.5.0' implementation 'androidx.core:core-google-shortcuts:1.0.0' + implementation 'androidx.test.ext:junit-ktx:1.1.5' debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7' testImplementation "com.google.truth:truth:1.1.3" testImplementation 'junit:junit:4.13.2' @@ -252,4 +259,9 @@ dependencies { // elib implementation 'foundation.e:elib:0.0.1-alpha11' + + + testImplementation 'org.mockito:mockito-core:5.0.0' + testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0' + testImplementation 'org.robolectric:robolectric:4.9' } diff --git a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt index 4e4b30127..37001fb5d 100644 --- a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt @@ -1,18 +1,24 @@ package foundation.e.apps.domain.login.repository +import android.content.Context import app.lounge.model.AnonymousAuthDataRequestBody import app.lounge.model.AuthDataResponse import app.lounge.networking.NetworkFetching +import app.lounge.storage.cache.configurations +import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject class LoginRepositoryImpl @Inject constructor( - private val networkFetching: NetworkFetching + private val networkFetching: NetworkFetching, + @ApplicationContext val applicationContext: Context ): LoginRepository { override suspend fun anonymousUser(authDataRequestBody: AnonymousAuthDataRequestBody): AuthDataResponse { return networkFetching.requestAuthData( anonymousAuthDataRequestBody = authDataRequestBody - ) + ).also { + applicationContext.configurations.authData = it.toString() + } } } diff --git a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt new file mode 100644 index 000000000..beaf715fd --- /dev/null +++ b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt @@ -0,0 +1,59 @@ +package foundation.e.apps.usecase.repository + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.rules.ActivityScenarioRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.platform.app.InstrumentationRegistry +import app.lounge.model.AnonymousAuthDataRequestBody +import app.lounge.model.AuthDataResponse +import app.lounge.networking.NetworkFetching +import com.aurora.gplayapi.data.models.AuthData +import foundation.e.apps.domain.login.repository.LoginRepository +import foundation.e.apps.domain.login.repository.LoginRepositoryImpl +import kotlinx.coroutines.test.runTest +import org.junit.Assert +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.MockitoAnnotations +import org.robolectric.RobolectricTestRunner +import retrofit2.Response +import java.util.Properties + +@RunWith(RobolectricTestRunner::class) +class LoginRepositoryTest { + + @Mock + lateinit var networkAPI: NetworkFetching + + lateinit var instrumentationContext: Context + + + @Before + fun setUp() { + MockitoAnnotations.openMocks(this) + instrumentationContext= ApplicationProvider.getApplicationContext() + } + + @Test + fun testRequestAuthData() = runTest { + Mockito.`when`(networkAPI.requestAuthData( + requestBodyData + )).thenReturn(AuthData("nisdande@murena.io", "")) + + val sut = LoginRepositoryImpl( + networkAPI, instrumentationContext) + val result = sut.anonymousUser(requestBodyData) + Assert.assertEquals(true, result is AuthDataResponse) + Assert.assertEquals("nisdande@murena.io", result.email) + } +} + +private val requestBodyData = AnonymousAuthDataRequestBody( + properties = Properties(), + userAgent = "testUserAgent" +) \ No newline at end of file diff --git a/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt b/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt index 46ef8cc8f..0d155607e 100644 --- a/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt +++ b/modules/src/androidTest/java/app/lounge/NetworkFetchingAPITest.kt @@ -99,9 +99,9 @@ class NetworkFetchingAPITest { ) } -private const val testUserAgent: String = "{\"package\":\"foundation.e.apps.debug\",\"version\":\"2.5.5.debug\",\"device\":\"coral\",\"api\":32,\"os_version\":\"1.11-s-20230511288805-dev-coral\",\"build_id\":\"319e25cd.20230630224839\"}" +const val testUserAgent: String = "{\"package\":\"foundation.e.apps.debug\",\"version\":\"2.5.5.debug\",\"device\":\"coral\",\"api\":32,\"os_version\":\"1.11-s-20230511288805-dev-coral\",\"build_id\":\"319e25cd.20230630224839\"}" -private val testSystemProperties = Properties().apply { +val testSystemProperties = Properties().apply { setProperty("UserReadableName", "coral-default") setProperty("Build.HARDWARE", "coral") setProperty("Build.RADIO", "g8150-00123-220402-B-8399852") -- GitLab From 7d34835954a8e3fe8150fbef8a2840aeaec53bac Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Tue, 1 Aug 2023 23:29:20 +0530 Subject: [PATCH 3/8] Adde testcase for anonymous user view model --- .../domain/login/usecase/UserLoginUseCase.kt | 8 +- .../apps/presentation/login/LoginViewModel.kt | 36 +++--- app/src/test/java/foundation/e/apps/Shared.kt | 15 +++ .../presentation/login/LoginViewModelTest.kt | 108 ++++++++++++++++++ .../usecase/repository/LoginRepositoryTest.kt | 34 ++---- 5 files changed, 155 insertions(+), 46 deletions(-) create mode 100644 app/src/test/java/foundation/e/apps/Shared.kt create mode 100644 app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt diff --git a/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt index e2e8b1813..fafa16e6a 100644 --- a/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt +++ b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt @@ -4,8 +4,8 @@ import app.lounge.model.AnonymousAuthDataRequestBody import app.lounge.model.AuthDataResponse import foundation.e.apps.domain.login.repository.LoginRepository import foundation.e.apps.utils.Resource -import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.single import retrofit2.HttpException import java.io.IOException import java.util.Properties @@ -15,10 +15,10 @@ class UserLoginUseCase @Inject constructor( private val loginRepository: LoginRepository, ) { - operator fun invoke( + suspend operator fun invoke( properties: Properties, userAgent: String - ): Flow> = flow { + ): Resource = flow { try { emit(Resource.Loading()) val userResponse: AuthDataResponse = loginRepository.anonymousUser( @@ -33,5 +33,5 @@ class UserLoginUseCase @Inject constructor( } catch(e: IOException) { emit(Resource.Error("Couldn't reach server. Check your internet connection.")) } - } + }.single() } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt b/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt index c209288af..e4fec4e76 100644 --- a/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt @@ -29,8 +29,6 @@ import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.ui.parentFragment.LoadingViewModel import foundation.e.apps.utils.Resource import foundation.e.apps.utils.SystemInfoProvider -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import java.util.Properties import javax.inject.Inject @@ -151,23 +149,25 @@ class LoginViewModel @Inject constructor( properties: Properties, userAgent: String = SystemInfoProvider.getAppBuildInfo() ) { - userLoginUseCase( - properties = properties, - userAgent = userAgent - ).onEach { result -> - when (result) { - is Resource.Success -> { - _loginState.value = LoginState(isLoggedIn = true) - } - is Resource.Error -> { - _loginState.value = LoginState( - error = result.message ?: "An unexpected error occured" - ) - } - is Resource.Loading -> { - _loginState.value = LoginState(isLoading = true) + viewModelScope.launch { + userLoginUseCase( + properties = properties, + userAgent = userAgent + ).also { result -> + when (result) { + is Resource.Success -> { + _loginState.value = LoginState(isLoggedIn = true) + } + is Resource.Error -> { + _loginState.value = LoginState( + error = result.message ?: "An unexpected error occured" + ) + } + is Resource.Loading -> { + _loginState.value = LoginState(isLoading = true) + } } } - }.launchIn(viewModelScope) + } } } diff --git a/app/src/test/java/foundation/e/apps/Shared.kt b/app/src/test/java/foundation/e/apps/Shared.kt new file mode 100644 index 000000000..0057d504f --- /dev/null +++ b/app/src/test/java/foundation/e/apps/Shared.kt @@ -0,0 +1,15 @@ +package foundation.e.apps + +import app.lounge.model.AnonymousAuthDataRequestBody +import com.aurora.gplayapi.data.models.AuthData +import java.util.Properties + + +val testAnonymousRequestBodyData = AnonymousAuthDataRequestBody( + properties = Properties(), + userAgent = "testUserAgent" +) + +val testAnonymousResponseData = AuthData("eOS@murena.io", "") + +const val loginFailureMessage = "Fail to login" \ No newline at end of file diff --git a/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt b/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt new file mode 100644 index 000000000..03760d35e --- /dev/null +++ b/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt @@ -0,0 +1,108 @@ +package foundation.e.apps.presentation.login + +import androidx.arch.core.executor.testing.InstantTaskExecutorRule +import foundation.e.apps.testAnonymousRequestBodyData +import foundation.e.apps.data.login.LoginSourceRepository +import foundation.e.apps.domain.login.usecase.UserLoginUseCase +import foundation.e.apps.loginFailureMessage +import foundation.e.apps.testAnonymousResponseData +import foundation.e.apps.util.getOrAwaitValue +import foundation.e.apps.utils.Resource +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.resetMain +import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.setMain +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.MockitoAnnotations + + +@OptIn(ExperimentalCoroutinesApi::class) +class LoginViewModelTest { + + private val testDispatcher = StandardTestDispatcher() + + @get:Rule + val instantTaskExecutorRule = InstantTaskExecutorRule() + + @Mock + lateinit var mockUserLoginUseCase: UserLoginUseCase + + @Mock + lateinit var loginRepository: LoginSourceRepository + + @Before + fun setUp() { + MockitoAnnotations.openMocks(this) + Dispatchers.setMain(testDispatcher) + } + + @Test + fun testAnonymousUserLoginStateForSuccess() = runTest{ + Mockito.`when`(mockUserLoginUseCase.invoke( + properties = testAnonymousRequestBodyData.properties, + userAgent = testAnonymousRequestBodyData.userAgent + )).thenReturn(Resource.Success(testAnonymousResponseData)) + + val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) + loginViewModel.authenticateAnonymousUser( + properties = testAnonymousRequestBodyData.properties, + userAgent = testAnonymousRequestBodyData.userAgent + ) + testDispatcher.scheduler.advanceUntilIdle() + val result = loginViewModel.loginState.getOrAwaitValue() + Assert.assertEquals(true, result.isLoggedIn) + Assert.assertEquals(false, result.isLoading) + } + + @Test + fun testAnonymousUserLoginStateForFailure() = runTest{ + Mockito.`when`(mockUserLoginUseCase.invoke( + properties = testAnonymousRequestBodyData.properties, + userAgent = testAnonymousRequestBodyData.userAgent + )).thenReturn(Resource.Error(loginFailureMessage)) + + val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) + loginViewModel.authenticateAnonymousUser( + properties = testAnonymousRequestBodyData.properties, + userAgent = testAnonymousRequestBodyData.userAgent + ) + testDispatcher.scheduler.advanceUntilIdle() + val result = loginViewModel.loginState.getOrAwaitValue() + Assert.assertEquals(false, result.isLoggedIn) + Assert.assertEquals(false, result.isLoading) + Assert.assertEquals(loginFailureMessage, result.error) + } + + @Test + fun testAnonymousUserLoginStateForLoading() = runTest{ + Mockito.`when`(mockUserLoginUseCase.invoke( + properties = testAnonymousRequestBodyData.properties, + userAgent = testAnonymousRequestBodyData.userAgent + )).thenReturn(Resource.Loading()) + + val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) + loginViewModel.authenticateAnonymousUser( + properties = testAnonymousRequestBodyData.properties, + userAgent = testAnonymousRequestBodyData.userAgent + ) + testDispatcher.scheduler.advanceUntilIdle() + val result = loginViewModel.loginState.getOrAwaitValue() + Assert.assertEquals(true, result.isLoading) + Assert.assertEquals(false, result.isLoggedIn) + } + + @After + fun tearDown() { + Dispatchers.resetMain() + } + +} + diff --git a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt index beaf715fd..77631b4f1 100644 --- a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt +++ b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt @@ -2,27 +2,20 @@ package foundation.e.apps.usecase.repository import android.content.Context import androidx.test.core.app.ApplicationProvider -import androidx.test.ext.junit.rules.ActivityScenarioRule -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import app.lounge.model.AnonymousAuthDataRequestBody import app.lounge.model.AuthDataResponse import app.lounge.networking.NetworkFetching -import com.aurora.gplayapi.data.models.AuthData -import foundation.e.apps.domain.login.repository.LoginRepository +import foundation.e.apps.testAnonymousRequestBodyData import foundation.e.apps.domain.login.repository.LoginRepositoryImpl +import foundation.e.apps.testAnonymousResponseData import kotlinx.coroutines.test.runTest import org.junit.Assert import org.junit.Before -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations import org.robolectric.RobolectricTestRunner -import retrofit2.Response -import java.util.Properties @RunWith(RobolectricTestRunner::class) class LoginRepositoryTest { @@ -30,7 +23,7 @@ class LoginRepositoryTest { @Mock lateinit var networkAPI: NetworkFetching - lateinit var instrumentationContext: Context + private lateinit var instrumentationContext: Context @Before @@ -41,19 +34,12 @@ class LoginRepositoryTest { @Test fun testRequestAuthData() = runTest { - Mockito.`when`(networkAPI.requestAuthData( - requestBodyData - )).thenReturn(AuthData("nisdande@murena.io", "")) - - val sut = LoginRepositoryImpl( - networkAPI, instrumentationContext) - val result = sut.anonymousUser(requestBodyData) - Assert.assertEquals(true, result is AuthDataResponse) - Assert.assertEquals("nisdande@murena.io", result.email) + Mockito.`when`(networkAPI.requestAuthData(testAnonymousRequestBodyData)) + .thenReturn(testAnonymousResponseData) + + val loginRepository = LoginRepositoryImpl(networkAPI, instrumentationContext) + val result: AuthDataResponse = loginRepository.anonymousUser(testAnonymousRequestBodyData) + Assert.assertNotNull(result) + Assert.assertEquals("eOS@murena.io", result.email) } } - -private val requestBodyData = AnonymousAuthDataRequestBody( - properties = Properties(), - userAgent = "testUserAgent" -) \ No newline at end of file -- GitLab From 2abcc41eac3f23972626120a3b3c1669ed4f72c1 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Fri, 4 Aug 2023 23:54:24 +0530 Subject: [PATCH 4/8] Update codebase with necessary changes --- app/build.gradle | 2 ++ .../login/repository/LoginRepository.kt | 4 ++-- .../login/repository/LoginRepositoryImpl.kt | 22 +++++++++++++------ .../domain/login/usecase/UserLoginUseCase.kt | 12 +++++----- .../usecase/repository/LoginRepositoryTest.kt | 22 ++++++++++--------- 5 files changed, 36 insertions(+), 26 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b451b98d0..6098ff118 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -153,6 +153,8 @@ allOpen { dependencies { + implementation project(':modules') + // TODO: Add splitinstall-lib to a repo https://gitlab.e.foundation/e/os/backlog/-/issues/628 api files('libs/splitinstall-lib.jar') diff --git a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt index a35c1bc98..e80c9203a 100644 --- a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt @@ -1,13 +1,13 @@ package foundation.e.apps.domain.login.repository import app.lounge.model.AnonymousAuthDataRequestBody -import app.lounge.model.AuthDataResponse +import com.aurora.gplayapi.data.models.AuthData interface LoginRepository { suspend fun anonymousUser( authDataRequestBody: AnonymousAuthDataRequestBody - ): AuthDataResponse + ): AuthData } \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt index 37001fb5d..004c32680 100644 --- a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt @@ -1,23 +1,31 @@ package foundation.e.apps.domain.login.repository import android.content.Context +import app.lounge.login.anonymous.AnonymousUser import app.lounge.model.AnonymousAuthDataRequestBody -import app.lounge.model.AuthDataResponse -import app.lounge.networking.NetworkFetching +import app.lounge.networking.NetworkResult import app.lounge.storage.cache.configurations +import com.aurora.gplayapi.data.models.AuthData import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject class LoginRepositoryImpl @Inject constructor( - private val networkFetching: NetworkFetching, + private val networkFetching: AnonymousUser, @ApplicationContext val applicationContext: Context ): LoginRepository { - override suspend fun anonymousUser(authDataRequestBody: AnonymousAuthDataRequestBody): AuthDataResponse { - return networkFetching.requestAuthData( + override suspend fun anonymousUser(authDataRequestBody: AnonymousAuthDataRequestBody): AuthData { + val result = networkFetching.requestAuthData( anonymousAuthDataRequestBody = authDataRequestBody - ).also { - applicationContext.configurations.authData = it.toString() + ) + + when(result) { + is NetworkResult.Error -> + throw Exception(result.errorMessage, result.exception) + is NetworkResult.Success -> { + applicationContext.configurations.authData = result.data.toString() + return result.data + } } } diff --git a/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt index fafa16e6a..9b0ea9a1b 100644 --- a/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt +++ b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt @@ -1,7 +1,7 @@ package foundation.e.apps.domain.login.usecase import app.lounge.model.AnonymousAuthDataRequestBody -import app.lounge.model.AuthDataResponse +import com.aurora.gplayapi.data.models.AuthData import foundation.e.apps.domain.login.repository.LoginRepository import foundation.e.apps.utils.Resource import kotlinx.coroutines.flow.flow @@ -18,20 +18,18 @@ class UserLoginUseCase @Inject constructor( suspend operator fun invoke( properties: Properties, userAgent: String - ): Resource = flow { + ): Resource = flow { try { emit(Resource.Loading()) - val userResponse: AuthDataResponse = loginRepository.anonymousUser( + val userResponse = loginRepository.anonymousUser( authDataRequestBody = AnonymousAuthDataRequestBody( properties = properties, userAgent = userAgent ) ) emit(Resource.Success(userResponse)) - } catch(e: HttpException) { - emit(Resource.Error(e.localizedMessage ?: "An unexpected error occured")) - } catch(e: IOException) { - emit(Resource.Error("Couldn't reach server. Check your internet connection.")) + } catch(e: Exception) { + emit(Resource.Error(e.localizedMessage)) } }.single() } \ No newline at end of file diff --git a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt index 77631b4f1..d16c32773 100644 --- a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt +++ b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt @@ -2,11 +2,6 @@ package foundation.e.apps.usecase.repository import android.content.Context import androidx.test.core.app.ApplicationProvider -import app.lounge.model.AuthDataResponse -import app.lounge.networking.NetworkFetching -import foundation.e.apps.testAnonymousRequestBodyData -import foundation.e.apps.domain.login.repository.LoginRepositoryImpl -import foundation.e.apps.testAnonymousResponseData import kotlinx.coroutines.test.runTest import org.junit.Assert import org.junit.Before @@ -17,11 +12,18 @@ import org.mockito.Mockito import org.mockito.MockitoAnnotations import org.robolectric.RobolectricTestRunner +import foundation.e.apps.domain.login.repository.LoginRepositoryImpl +import foundation.e.apps.testAnonymousRequestBodyData +import foundation.e.apps.testAnonymousResponseData + +import app.lounge.login.anonymous.AnonymousUser +import app.lounge.networking.NetworkResult + @RunWith(RobolectricTestRunner::class) class LoginRepositoryTest { @Mock - lateinit var networkAPI: NetworkFetching + lateinit var anonymousUser: AnonymousUser private lateinit var instrumentationContext: Context @@ -34,11 +36,11 @@ class LoginRepositoryTest { @Test fun testRequestAuthData() = runTest { - Mockito.`when`(networkAPI.requestAuthData(testAnonymousRequestBodyData)) - .thenReturn(testAnonymousResponseData) + Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) + .thenReturn(NetworkResult.Success(testAnonymousResponseData)) - val loginRepository = LoginRepositoryImpl(networkAPI, instrumentationContext) - val result: AuthDataResponse = loginRepository.anonymousUser(testAnonymousRequestBodyData) + val loginRepository = LoginRepositoryImpl(anonymousUser, instrumentationContext) + val result = loginRepository.anonymousUser(testAnonymousRequestBodyData) Assert.assertNotNull(result) Assert.assertEquals("eOS@murena.io", result.email) } -- GitLab From 43b8e755bcaf99a58937d7ed3e1219a6afafd034 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Sat, 5 Aug 2023 23:24:47 +0530 Subject: [PATCH 5/8] Refine test case for domain and ui layer --- app/src/test/java/foundation/e/apps/Shared.kt | 4 ++- .../presentation/login/LoginViewModelTest.kt | 6 ++--- .../usecase/repository/LoginRepositoryTest.kt | 27 ++++++++++++++++--- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/app/src/test/java/foundation/e/apps/Shared.kt b/app/src/test/java/foundation/e/apps/Shared.kt index 0057d504f..986e5f1cd 100644 --- a/app/src/test/java/foundation/e/apps/Shared.kt +++ b/app/src/test/java/foundation/e/apps/Shared.kt @@ -12,4 +12,6 @@ val testAnonymousRequestBodyData = AnonymousAuthDataRequestBody( val testAnonymousResponseData = AuthData("eOS@murena.io", "") -const val loginFailureMessage = "Fail to login" \ No newline at end of file +const val loginFailureMessage = "Fail to login" + +val testFailureException: Exception = Exception(loginFailureMessage) \ No newline at end of file diff --git a/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt b/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt index 03760d35e..93f65c438 100644 --- a/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt +++ b/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt @@ -45,7 +45,7 @@ class LoginViewModelTest { } @Test - fun testAnonymousUserLoginStateForSuccess() = runTest{ + fun testOnSuccessReturnLogInStateTrue() = runTest{ Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent @@ -63,7 +63,7 @@ class LoginViewModelTest { } @Test - fun testAnonymousUserLoginStateForFailure() = runTest{ + fun testOnFailureReturnLogInStateFalseWithError() = runTest{ Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent @@ -82,7 +82,7 @@ class LoginViewModelTest { } @Test - fun testAnonymousUserLoginStateForLoading() = runTest{ + fun testOnLoadingReturnLogInStateFalse() = runTest{ Mockito.`when`(mockUserLoginUseCase.invoke( properties = testAnonymousRequestBodyData.properties, userAgent = testAnonymousRequestBodyData.userAgent diff --git a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt index d16c32773..9d3fbda3f 100644 --- a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt +++ b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt @@ -18,6 +18,8 @@ import foundation.e.apps.testAnonymousResponseData import app.lounge.login.anonymous.AnonymousUser import app.lounge.networking.NetworkResult +import foundation.e.apps.loginFailureMessage +import foundation.e.apps.testFailureException @RunWith(RobolectricTestRunner::class) class LoginRepositoryTest { @@ -35,13 +37,32 @@ class LoginRepositoryTest { } @Test - fun testRequestAuthData() = runTest { + fun testOnSuccessReturnAuthData() = runTest { Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) .thenReturn(NetworkResult.Success(testAnonymousResponseData)) - val loginRepository = LoginRepositoryImpl(anonymousUser, instrumentationContext) - val result = loginRepository.anonymousUser(testAnonymousRequestBodyData) + val result = LoginRepositoryImpl(anonymousUser, instrumentationContext) + .run { + anonymousUser(testAnonymousRequestBodyData) + } + Assert.assertNotNull(result) Assert.assertEquals("eOS@murena.io", result.email) } + + @Test + fun testOnFailureReturnErrorWithException() = runTest { + Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) + .thenReturn(NetworkResult.Error( + exception = testFailureException, + code = 1, + errorMessage = loginFailureMessage + )) + runCatching { + LoginRepositoryImpl(anonymousUser, instrumentationContext) + .run { anonymousUser(testAnonymousRequestBodyData) } + }.onFailure { error -> + Assert.assertEquals(testFailureException.message, error.message) + } + } } -- GitLab From a1d79950c070d67f7fe13646f3cf000f51a478cf Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Sat, 5 Aug 2023 23:27:34 +0530 Subject: [PATCH 6/8] Added copyright text --- .../login/repository/LoginRepository.kt | 19 +++++++++++++++++++ .../login/repository/LoginRepositoryImpl.kt | 19 +++++++++++++++++++ .../domain/login/usecase/UserLoginUseCase.kt | 19 +++++++++++++++++++ .../e/apps/presentation/login/LoginState.kt | 19 +++++++++++++++++++ .../java/foundation/e/apps/utils/Resource.kt | 19 +++++++++++++++++++ app/src/test/java/foundation/e/apps/Shared.kt | 19 +++++++++++++++++++ .../presentation/login/LoginViewModelTest.kt | 19 +++++++++++++++++++ .../usecase/repository/LoginRepositoryTest.kt | 19 +++++++++++++++++++ 8 files changed, 152 insertions(+) diff --git a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt index e80c9203a..94533699a 100644 --- a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + package foundation.e.apps.domain.login.repository import app.lounge.model.AnonymousAuthDataRequestBody diff --git a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt index 004c32680..b5f36c1be 100644 --- a/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + package foundation.e.apps.domain.login.repository import android.content.Context diff --git a/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt index 9b0ea9a1b..ee936b572 100644 --- a/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt +++ b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + package foundation.e.apps.domain.login.usecase import app.lounge.model.AnonymousAuthDataRequestBody diff --git a/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt b/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt index 400fb86bc..b7e3d0f90 100644 --- a/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt +++ b/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + package foundation.e.apps.presentation.login diff --git a/app/src/main/java/foundation/e/apps/utils/Resource.kt b/app/src/main/java/foundation/e/apps/utils/Resource.kt index f598e91e5..7c468ab47 100644 --- a/app/src/main/java/foundation/e/apps/utils/Resource.kt +++ b/app/src/main/java/foundation/e/apps/utils/Resource.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + package foundation.e.apps.utils diff --git a/app/src/test/java/foundation/e/apps/Shared.kt b/app/src/test/java/foundation/e/apps/Shared.kt index 986e5f1cd..b82344dfa 100644 --- a/app/src/test/java/foundation/e/apps/Shared.kt +++ b/app/src/test/java/foundation/e/apps/Shared.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + package foundation.e.apps import app.lounge.model.AnonymousAuthDataRequestBody diff --git a/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt b/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt index 93f65c438..cc14f35c2 100644 --- a/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt +++ b/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + package foundation.e.apps.presentation.login import androidx.arch.core.executor.testing.InstantTaskExecutorRule diff --git a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt index 9d3fbda3f..25a9f06d5 100644 --- a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt +++ b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt @@ -1,3 +1,22 @@ +/* + * Copyright MURENA SAS 2023 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + package foundation.e.apps.usecase.repository import android.content.Context -- GitLab From 9dce99b567b059daab5f2cf746788f8de8d1a66f Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Mon, 21 Aug 2023 23:45:00 +0530 Subject: [PATCH 7/8] Updated viewmodel with flow and handled testcases --- app/build.gradle | 2 + .../apps/presentation/login/LoginViewModel.kt | 14 ++- .../presentation/login/LoginViewModelTest.kt | 47 +++------- .../usecase/repository/LoginRepositoryTest.kt | 87 ------------------- 4 files changed, 21 insertions(+), 129 deletions(-) delete mode 100644 app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt diff --git a/app/build.gradle b/app/build.gradle index 9ce0bc8cd..81ed596b6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -137,6 +137,7 @@ android { testOptions { unitTests { includeAndroidResources = true + returnDefaultValues = true } } } @@ -262,4 +263,5 @@ dependencies { testImplementation 'org.mockito:mockito-core:5.0.0' testImplementation 'com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0' testImplementation 'org.robolectric:robolectric:4.9' + testImplementation 'org.json:json:20180813' // Added to avoid SystemInfoProvider.getAppBuildInfo() mock error } diff --git a/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt b/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt index e4fec4e76..5655020e3 100644 --- a/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt @@ -29,6 +29,8 @@ import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.ui.parentFragment.LoadingViewModel import foundation.e.apps.utils.Resource import foundation.e.apps.utils.SystemInfoProvider +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import java.util.Properties import javax.inject.Inject @@ -145,15 +147,9 @@ class LoginViewModel @Inject constructor( val loginState: LiveData = _loginState - fun authenticateAnonymousUser( - properties: Properties, - userAgent: String = SystemInfoProvider.getAppBuildInfo() - ) { + fun authenticateAnonymousUser() { viewModelScope.launch { - userLoginUseCase( - properties = properties, - userAgent = userAgent - ).also { result -> + userLoginUseCase.anonymousUser().onEach {result -> when (result) { is Resource.Success -> { _loginState.value = LoginState(isLoggedIn = true) @@ -167,7 +163,7 @@ class LoginViewModel @Inject constructor( _loginState.value = LoginState(isLoading = true) } } - } + }.collect() } } } diff --git a/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt b/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt index cc14f35c2..16b2d5d77 100644 --- a/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt +++ b/app/src/test/java/foundation/e/apps/presentation/login/LoginViewModelTest.kt @@ -16,11 +16,9 @@ * along with this program. If not, see . */ - package foundation.e.apps.presentation.login import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import foundation.e.apps.testAnonymousRequestBodyData import foundation.e.apps.data.login.LoginSourceRepository import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.loginFailureMessage @@ -29,6 +27,7 @@ import foundation.e.apps.util.getOrAwaitValue import foundation.e.apps.utils.Resource import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.resetMain import kotlinx.coroutines.test.runTest @@ -42,14 +41,13 @@ import org.mockito.Mock import org.mockito.Mockito import org.mockito.MockitoAnnotations - @OptIn(ExperimentalCoroutinesApi::class) class LoginViewModelTest { private val testDispatcher = StandardTestDispatcher() @get:Rule - val instantTaskExecutorRule = InstantTaskExecutorRule() + val rule = InstantTaskExecutorRule() @Mock lateinit var mockUserLoginUseCase: UserLoginUseCase @@ -64,17 +62,12 @@ class LoginViewModelTest { } @Test - fun testOnSuccessReturnLogInStateTrue() = runTest{ - Mockito.`when`(mockUserLoginUseCase.invoke( - properties = testAnonymousRequestBodyData.properties, - userAgent = testAnonymousRequestBodyData.userAgent - )).thenReturn(Resource.Success(testAnonymousResponseData)) + fun testOnSuccessReturnLogInStateTrue() = runTest { + Mockito.`when`(mockUserLoginUseCase.anonymousUser()) + .thenReturn(flowOf(Resource.Success(testAnonymousResponseData))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) - loginViewModel.authenticateAnonymousUser( - properties = testAnonymousRequestBodyData.properties, - userAgent = testAnonymousRequestBodyData.userAgent - ) + loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(true, result.isLoggedIn) @@ -82,17 +75,12 @@ class LoginViewModelTest { } @Test - fun testOnFailureReturnLogInStateFalseWithError() = runTest{ - Mockito.`when`(mockUserLoginUseCase.invoke( - properties = testAnonymousRequestBodyData.properties, - userAgent = testAnonymousRequestBodyData.userAgent - )).thenReturn(Resource.Error(loginFailureMessage)) + fun testOnFailureReturnLogInStateFalseWithError() = runTest { + Mockito.`when`(mockUserLoginUseCase.anonymousUser()) + .thenReturn(flowOf(Resource.Error(loginFailureMessage, null))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) - loginViewModel.authenticateAnonymousUser( - properties = testAnonymousRequestBodyData.properties, - userAgent = testAnonymousRequestBodyData.userAgent - ) + loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(false, result.isLoggedIn) @@ -101,17 +89,12 @@ class LoginViewModelTest { } @Test - fun testOnLoadingReturnLogInStateFalse() = runTest{ - Mockito.`when`(mockUserLoginUseCase.invoke( - properties = testAnonymousRequestBodyData.properties, - userAgent = testAnonymousRequestBodyData.userAgent - )).thenReturn(Resource.Loading()) + fun testOnLoadingReturnLogInStateFalse() = runTest { + Mockito.`when`(mockUserLoginUseCase.anonymousUser()) + .thenReturn(flowOf(Resource.Loading(null))) val loginViewModel = LoginViewModel(loginRepository, mockUserLoginUseCase) - loginViewModel.authenticateAnonymousUser( - properties = testAnonymousRequestBodyData.properties, - userAgent = testAnonymousRequestBodyData.userAgent - ) + loginViewModel.authenticateAnonymousUser() testDispatcher.scheduler.advanceUntilIdle() val result = loginViewModel.loginState.getOrAwaitValue() Assert.assertEquals(true, result.isLoading) @@ -122,6 +105,4 @@ class LoginViewModelTest { fun tearDown() { Dispatchers.resetMain() } - } - diff --git a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt b/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt deleted file mode 100644 index 25a9f06d5..000000000 --- a/app/src/test/java/foundation/e/apps/usecase/repository/LoginRepositoryTest.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright MURENA SAS 2023 - * Apps Quickly and easily install Android apps onto your device! - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -package foundation.e.apps.usecase.repository - -import android.content.Context -import androidx.test.core.app.ApplicationProvider -import kotlinx.coroutines.test.runTest -import org.junit.Assert -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.Mockito -import org.mockito.MockitoAnnotations -import org.robolectric.RobolectricTestRunner - -import foundation.e.apps.domain.login.repository.LoginRepositoryImpl -import foundation.e.apps.testAnonymousRequestBodyData -import foundation.e.apps.testAnonymousResponseData - -import app.lounge.login.anonymous.AnonymousUser -import app.lounge.networking.NetworkResult -import foundation.e.apps.loginFailureMessage -import foundation.e.apps.testFailureException - -@RunWith(RobolectricTestRunner::class) -class LoginRepositoryTest { - - @Mock - lateinit var anonymousUser: AnonymousUser - - private lateinit var instrumentationContext: Context - - - @Before - fun setUp() { - MockitoAnnotations.openMocks(this) - instrumentationContext= ApplicationProvider.getApplicationContext() - } - - @Test - fun testOnSuccessReturnAuthData() = runTest { - Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) - .thenReturn(NetworkResult.Success(testAnonymousResponseData)) - - val result = LoginRepositoryImpl(anonymousUser, instrumentationContext) - .run { - anonymousUser(testAnonymousRequestBodyData) - } - - Assert.assertNotNull(result) - Assert.assertEquals("eOS@murena.io", result.email) - } - - @Test - fun testOnFailureReturnErrorWithException() = runTest { - Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) - .thenReturn(NetworkResult.Error( - exception = testFailureException, - code = 1, - errorMessage = loginFailureMessage - )) - runCatching { - LoginRepositoryImpl(anonymousUser, instrumentationContext) - .run { anonymousUser(testAnonymousRequestBodyData) } - }.onFailure { error -> - Assert.assertEquals(testFailureException.message, error.message) - } - } -} -- GitLab From eeab7fa22fe9ffb65ee287954574e3a4ed708cf0 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Mon, 21 Aug 2023 23:47:12 +0530 Subject: [PATCH 8/8] Fix Klint issues --- app/src/main/java/foundation/e/apps/di/LoginModule.kt | 1 - .../java/foundation/e/apps/presentation/login/LoginState.kt | 2 -- .../foundation/e/apps/presentation/login/LoginViewModel.kt | 6 +----- app/src/main/java/foundation/e/apps/ui/MainActivity.kt | 3 +-- .../foundation/e/apps/ui/parentFragment/TimeoutFragment.kt | 2 +- .../java/foundation/e/apps/ui/settings/SettingsFragment.kt | 2 +- .../foundation/e/apps/ui/setup/signin/SignInFragment.kt | 2 +- .../e/apps/ui/setup/signin/google/GoogleSignInFragment.kt | 2 +- 8 files changed, 6 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/di/LoginModule.kt b/app/src/main/java/foundation/e/apps/di/LoginModule.kt index 9708c9a8e..3df9857af 100644 --- a/app/src/main/java/foundation/e/apps/di/LoginModule.kt +++ b/app/src/main/java/foundation/e/apps/di/LoginModule.kt @@ -45,5 +45,4 @@ object LoginModule { ): UserLoginUseCase { return UserLoginUseCase(loginRepositoryImpl) } - } diff --git a/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt b/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt index b7e3d0f90..23f54bc34 100644 --- a/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt +++ b/app/src/main/java/foundation/e/apps/presentation/login/LoginState.kt @@ -16,10 +16,8 @@ * along with this program. If not, see . */ - package foundation.e.apps.presentation.login - data class LoginState( val isLoading: Boolean = false, val isLoggedIn: Boolean = false, diff --git a/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt b/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt index 5655020e3..18da1ca6e 100644 --- a/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt +++ b/app/src/main/java/foundation/e/apps/presentation/login/LoginViewModel.kt @@ -28,11 +28,9 @@ import foundation.e.apps.data.login.LoginSourceRepository import foundation.e.apps.domain.login.usecase.UserLoginUseCase import foundation.e.apps.ui.parentFragment.LoadingViewModel import foundation.e.apps.utils.Resource -import foundation.e.apps.utils.SystemInfoProvider import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch -import java.util.Properties import javax.inject.Inject /** @@ -142,14 +140,12 @@ class LoginViewModel @Inject constructor( } } - private val _loginState: MutableLiveData = MutableLiveData() val loginState: LiveData = _loginState - fun authenticateAnonymousUser() { viewModelScope.launch { - userLoginUseCase.anonymousUser().onEach {result -> + userLoginUseCase.anonymousUser().onEach { result -> when (result) { is Resource.Success -> { _loginState.value = LoginState(isLoggedIn = true) diff --git a/app/src/main/java/foundation/e/apps/ui/MainActivity.kt b/app/src/main/java/foundation/e/apps/ui/MainActivity.kt index 096c4b98f..82e5f4ce1 100644 --- a/app/src/main/java/foundation/e/apps/ui/MainActivity.kt +++ b/app/src/main/java/foundation/e/apps/ui/MainActivity.kt @@ -46,15 +46,14 @@ import foundation.e.apps.R import foundation.e.apps.data.enums.Status import foundation.e.apps.data.fusedDownload.models.FusedDownload import foundation.e.apps.data.login.AuthObject -import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.data.login.exceptions.GPlayValidationException import foundation.e.apps.databinding.ActivityMainBinding import foundation.e.apps.install.updates.UpdatesNotifier import foundation.e.apps.install.workmanager.InstallWorkManager +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.ui.application.subFrags.ApplicationDialogFragment import foundation.e.apps.ui.purchase.AppPurchaseFragmentDirections import foundation.e.apps.ui.settings.SettingsFragment -import foundation.e.apps.ui.setup.signin.SignInViewModel import foundation.e.apps.utils.SystemInfoProvider import foundation.e.apps.utils.eventBus.AppEvent import foundation.e.apps.utils.eventBus.EventBus diff --git a/app/src/main/java/foundation/e/apps/ui/parentFragment/TimeoutFragment.kt b/app/src/main/java/foundation/e/apps/ui/parentFragment/TimeoutFragment.kt index 9a7f8eb10..9e395ae2a 100644 --- a/app/src/main/java/foundation/e/apps/ui/parentFragment/TimeoutFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/parentFragment/TimeoutFragment.kt @@ -34,13 +34,13 @@ import foundation.e.apps.R import foundation.e.apps.data.enums.User import foundation.e.apps.data.login.AuthObject import foundation.e.apps.data.login.LoginSourceGPlay -import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.data.login.exceptions.CleanApkException import foundation.e.apps.data.login.exceptions.GPlayException import foundation.e.apps.data.login.exceptions.GPlayLoginException import foundation.e.apps.data.login.exceptions.GPlayValidationException import foundation.e.apps.data.login.exceptions.UnknownSourceException import foundation.e.apps.databinding.DialogErrorLogBinding +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.ui.MainActivityViewModel import timber.log.Timber diff --git a/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt b/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt index 4a717877d..9865ff7cd 100644 --- a/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/settings/SettingsFragment.kt @@ -40,9 +40,9 @@ import foundation.e.apps.BuildConfig import foundation.e.apps.R import foundation.e.apps.data.enums.User import foundation.e.apps.data.fused.UpdatesDao -import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.databinding.CustomPreferenceBinding import foundation.e.apps.install.updates.UpdatesWorkManager +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.ui.MainActivityViewModel import foundation.e.apps.utils.SystemInfoProvider import timber.log.Timber diff --git a/app/src/main/java/foundation/e/apps/ui/setup/signin/SignInFragment.kt b/app/src/main/java/foundation/e/apps/ui/setup/signin/SignInFragment.kt index 7ed9eb765..e9ce89eb3 100644 --- a/app/src/main/java/foundation/e/apps/ui/setup/signin/SignInFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/setup/signin/SignInFragment.kt @@ -7,9 +7,9 @@ import androidx.lifecycle.ViewModelProvider import androidx.navigation.findNavController import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.R -import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.databinding.FragmentSignInBinding import foundation.e.apps.di.CommonUtilsModule.safeNavigate +import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.utils.showGoogleSignInAlertDialog @AndroidEntryPoint diff --git a/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt b/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt index ed964d86c..3ecc77843 100644 --- a/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt +++ b/app/src/main/java/foundation/e/apps/ui/setup/signin/google/GoogleSignInFragment.kt @@ -32,9 +32,9 @@ import androidx.navigation.findNavController import dagger.hilt.android.AndroidEntryPoint import foundation.e.apps.R import foundation.e.apps.data.gplay.utils.AC2DMUtil -import foundation.e.apps.presentation.login.LoginViewModel import foundation.e.apps.databinding.FragmentGoogleSigninBinding import foundation.e.apps.di.CommonUtilsModule.safeNavigate +import foundation.e.apps.presentation.login.LoginViewModel @AndroidEntryPoint class GoogleSignInFragment : Fragment(R.layout.fragment_google_signin) { -- GitLab