From bcbdf18d9ccfa24cf6d71bfe079302b640e27f29 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Fri, 21 Jul 2023 19:16:29 +0530 Subject: [PATCH 01/13] 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 02/13] 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 03/13] 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 04/13] 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 05/13] 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 06/13] 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 436461d75f831d9757eac1de4793907f5602522f Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Wed, 9 Aug 2023 21:57:24 +0530 Subject: [PATCH 07/13] Implement domain layer for anonymous users --- app/build.gradle | 6 ++ .../login/repository/LoginRepository.kt | 29 +++++++ .../login/repository/LoginRepositoryImpl.kt | 49 +++++++++++ .../domain/login/usecase/UserLoginUseCase.kt | 51 +++++++++++ .../java/foundation/e/apps/utils/Resource.kt | 25 ++++++ app/src/test/java/foundation/e/apps/Shared.kt | 34 ++++++++ .../login/repository/LoginRepositoryTest.kt | 84 +++++++++++++++++++ 7 files changed, 278 insertions(+) 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/utils/Resource.kt create mode 100644 app/src/test/java/foundation/e/apps/Shared.kt create mode 100644 app/src/test/java/foundation/e/apps/domain/login/repository/LoginRepositoryTest.kt diff --git a/app/build.gradle b/app/build.gradle index 1d0b1c0d7..26137f69f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -147,6 +147,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') @@ -250,4 +252,8 @@ 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/LoginRepository.kt b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt new file mode 100644 index 000000000..19ff48c34 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepository.kt @@ -0,0 +1,29 @@ +/* + * 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 +import com.aurora.gplayapi.data.models.AuthData + +interface LoginRepository { + + suspend fun anonymousUser( + authDataRequestBody: AnonymousAuthDataRequestBody + ): AuthData +} 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..ad61667d8 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/domain/login/repository/LoginRepositoryImpl.kt @@ -0,0 +1,49 @@ +/* + * 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 +import app.lounge.login.anonymous.AnonymousUser +import app.lounge.model.AnonymousAuthDataRequestBody +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: AnonymousUser, + @ApplicationContext val applicationContext: Context +) : LoginRepository { + + override suspend fun anonymousUser(authDataRequestBody: AnonymousAuthDataRequestBody): AuthData { + val result = networkFetching.requestAuthData( + anonymousAuthDataRequestBody = authDataRequestBody + ) + + 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 new file mode 100644 index 000000000..a62ee1961 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/domain/login/usecase/UserLoginUseCase.kt @@ -0,0 +1,51 @@ +/* + * 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 +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 +import kotlinx.coroutines.flow.single +import java.util.Properties +import javax.inject.Inject + +class UserLoginUseCase @Inject constructor( + private val loginRepository: LoginRepository, +) { + + suspend operator fun invoke( + properties: Properties, + userAgent: String + ): Resource = flow { + try { + emit(Resource.Loading()) + val userResponse = loginRepository.anonymousUser( + authDataRequestBody = AnonymousAuthDataRequestBody( + properties = properties, + userAgent = userAgent + ) + ) + emit(Resource.Success(userResponse)) + } catch (e: Exception) { + emit(Resource.Error(e.localizedMessage)) + } + }.single() +} 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..7a471a5f1 --- /dev/null +++ b/app/src/main/java/foundation/e/apps/utils/Resource.kt @@ -0,0 +1,25 @@ +/* + * 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 + +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) +} 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..2199b514f --- /dev/null +++ b/app/src/test/java/foundation/e/apps/Shared.kt @@ -0,0 +1,34 @@ +/* + * 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 +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" + +val testFailureException: Exception = Exception(loginFailureMessage) diff --git a/app/src/test/java/foundation/e/apps/domain/login/repository/LoginRepositoryTest.kt b/app/src/test/java/foundation/e/apps/domain/login/repository/LoginRepositoryTest.kt new file mode 100644 index 000000000..3d1cf6c27 --- /dev/null +++ b/app/src/test/java/foundation/e/apps/domain/login/repository/LoginRepositoryTest.kt @@ -0,0 +1,84 @@ +/* + * 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 +import androidx.test.core.app.ApplicationProvider +import app.lounge.login.anonymous.AnonymousUser +import app.lounge.networking.NetworkResult +import foundation.e.apps.loginFailureMessage +import foundation.e.apps.testAnonymousRequestBodyData +import foundation.e.apps.testAnonymousResponseData +import foundation.e.apps.testFailureException +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 + +@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 c99026301943a3ced54d2dcd0421879de566cb85 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Wed, 9 Aug 2023 22:17:10 +0530 Subject: [PATCH 08/13] Modify variable names --- .../e/apps/domain/login/repository/LoginRepositoryImpl.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 ad61667d8..e11159b2b 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 @@ -28,12 +28,12 @@ import dagger.hilt.android.qualifiers.ApplicationContext import javax.inject.Inject class LoginRepositoryImpl @Inject constructor( - private val networkFetching: AnonymousUser, + private val anonymousUser: AnonymousUser, @ApplicationContext val applicationContext: Context ) : LoginRepository { override suspend fun anonymousUser(authDataRequestBody: AnonymousAuthDataRequestBody): AuthData { - val result = networkFetching.requestAuthData( + val result = anonymousUser.requestAuthData( anonymousAuthDataRequestBody = authDataRequestBody ) -- GitLab From 086312e957ef7a887d5ae3feee2e7338e516ddbf Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Fri, 11 Aug 2023 22:04:09 +0530 Subject: [PATCH 09/13] Modified code comment and Resource state structure --- .../domain/login/usecase/UserLoginUseCase.kt | 4 ++-- .../java/foundation/e/apps/utils/Resource.kt | 23 +++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) 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 a62ee1961..dd0d2af07 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 @@ -31,12 +31,12 @@ class UserLoginUseCase @Inject constructor( private val loginRepository: LoginRepository, ) { - suspend operator fun invoke( + suspend fun anonymousUser( properties: Properties, userAgent: String ): Resource = flow { try { - emit(Resource.Loading()) + emit(Resource.Loading) val userResponse = loginRepository.anonymousUser( authDataRequestBody = AnonymousAuthDataRequestBody( properties = properties, 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 7a471a5f1..81bee55fc 100644 --- a/app/src/main/java/foundation/e/apps/utils/Resource.kt +++ b/app/src/main/java/foundation/e/apps/utils/Resource.kt @@ -18,8 +18,23 @@ 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) +/** + * Class represents the different states of a resource for user case layer + */ +sealed class Resource { + /** + * Represents a successful state of the resource with data. + * @param data The data associated with the resource. + */ + class Success(val data: T) : Resource() + /** + * Represents an error state of the resource with an error message. + * @param message The error message associated with the resource. + */ + class Error(message: String) : Resource() + + /** + * Represents a loading state of the resource. + */ + object Loading : Resource() } -- GitLab From ddce8136cf7747638eb55602ee5f762726c9c298 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Sat, 19 Aug 2023 16:22:36 +0530 Subject: [PATCH 10/13] Remove anonymousUser request parameter from api --- .../login/repository/LoginRepository.kt | 5 +-- .../login/repository/LoginRepositoryImpl.kt | 14 +++++-- .../domain/login/usecase/UserLoginUseCase.kt | 14 +------ app/src/test/java/foundation/e/apps/Shared.kt | 15 +++---- .../login/repository/LoginRepositoryTest.kt | 39 ++++++++++--------- 5 files changed, 42 insertions(+), 45 deletions(-) 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 19ff48c34..45edb8773 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 @@ -18,12 +18,9 @@ package foundation.e.apps.domain.login.repository -import app.lounge.model.AnonymousAuthDataRequestBody import com.aurora.gplayapi.data.models.AuthData interface LoginRepository { - suspend fun anonymousUser( - authDataRequestBody: AnonymousAuthDataRequestBody - ): AuthData + suspend fun anonymousUser(): AuthData } 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 e11159b2b..58e970348 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 @@ -25,16 +25,24 @@ 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 foundation.e.apps.utils.SystemInfoProvider +import java.util.Properties import javax.inject.Inject class LoginRepositoryImpl @Inject constructor( + @ApplicationContext val applicationContext: Context, + private val properties: Properties, private val anonymousUser: AnonymousUser, - @ApplicationContext val applicationContext: Context ) : LoginRepository { - override suspend fun anonymousUser(authDataRequestBody: AnonymousAuthDataRequestBody): AuthData { + private val userAgent: String by lazy { SystemInfoProvider.getAppBuildInfo() } + + override suspend fun anonymousUser(): AuthData { val result = anonymousUser.requestAuthData( - anonymousAuthDataRequestBody = authDataRequestBody + anonymousAuthDataRequestBody = AnonymousAuthDataRequestBody( + properties = properties, + userAgent = userAgent + ) ) when (result) { 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 dd0d2af07..33cee4402 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 @@ -18,31 +18,21 @@ package foundation.e.apps.domain.login.usecase -import app.lounge.model.AnonymousAuthDataRequestBody 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 import kotlinx.coroutines.flow.single -import java.util.Properties import javax.inject.Inject class UserLoginUseCase @Inject constructor( private val loginRepository: LoginRepository, ) { - suspend fun anonymousUser( - properties: Properties, - userAgent: String - ): Resource = flow { + suspend fun anonymousUser(): Resource = flow { try { emit(Resource.Loading) - val userResponse = loginRepository.anonymousUser( - authDataRequestBody = AnonymousAuthDataRequestBody( - properties = properties, - userAgent = userAgent - ) - ) + val userResponse = loginRepository.anonymousUser() emit(Resource.Success(userResponse)) } catch (e: Exception) { emit(Resource.Error(e.localizedMessage)) diff --git a/app/src/test/java/foundation/e/apps/Shared.kt b/app/src/test/java/foundation/e/apps/Shared.kt index 2199b514f..95f108bec 100644 --- a/app/src/test/java/foundation/e/apps/Shared.kt +++ b/app/src/test/java/foundation/e/apps/Shared.kt @@ -20,15 +20,16 @@ package foundation.e.apps import app.lounge.model.AnonymousAuthDataRequestBody import com.aurora.gplayapi.data.models.AuthData +import foundation.e.apps.utils.SystemInfoProvider import java.util.Properties -val testAnonymousRequestBodyData = AnonymousAuthDataRequestBody( +const val testEmailAddress: String = "eOS@murena.io" +const val loginFailureMessage = "Fail to login" +val testFailureException: Exception = Exception(loginFailureMessage) + +val testAnonymousRequestData = AnonymousAuthDataRequestBody( properties = Properties(), - userAgent = "testUserAgent" + userAgent = SystemInfoProvider.getAppBuildInfo() ) -val testAnonymousResponseData = AuthData("eOS@murena.io", "") - -const val loginFailureMessage = "Fail to login" - -val testFailureException: Exception = Exception(loginFailureMessage) +val testAnonymousResponseData = AuthData(testEmailAddress, "") diff --git a/app/src/test/java/foundation/e/apps/domain/login/repository/LoginRepositoryTest.kt b/app/src/test/java/foundation/e/apps/domain/login/repository/LoginRepositoryTest.kt index 3d1cf6c27..5e9f368b0 100644 --- a/app/src/test/java/foundation/e/apps/domain/login/repository/LoginRepositoryTest.kt +++ b/app/src/test/java/foundation/e/apps/domain/login/repository/LoginRepositoryTest.kt @@ -23,8 +23,9 @@ import androidx.test.core.app.ApplicationProvider import app.lounge.login.anonymous.AnonymousUser import app.lounge.networking.NetworkResult import foundation.e.apps.loginFailureMessage -import foundation.e.apps.testAnonymousRequestBodyData +import foundation.e.apps.testAnonymousRequestData import foundation.e.apps.testAnonymousResponseData +import foundation.e.apps.testEmailAddress import foundation.e.apps.testFailureException import kotlinx.coroutines.test.runTest import org.junit.Assert @@ -42,41 +43,41 @@ class LoginRepositoryTest { @Mock lateinit var anonymousUser: AnonymousUser - private lateinit var instrumentationContext: Context + private lateinit var context: Context @Before fun setUp() { MockitoAnnotations.openMocks(this) - instrumentationContext = ApplicationProvider.getApplicationContext() + context = ApplicationProvider.getApplicationContext() } @Test fun testOnSuccessReturnAuthData() = runTest { - Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) - .thenReturn(NetworkResult.Success(testAnonymousResponseData)) + Mockito.`when`( + anonymousUser.requestAuthData(testAnonymousRequestData) + ).thenReturn(NetworkResult.Success(testAnonymousResponseData)) - val result = LoginRepositoryImpl(anonymousUser, instrumentationContext) - .run { - anonymousUser(testAnonymousRequestBodyData) - } + val result = LoginRepositoryImpl(context, testAnonymousRequestData.properties, anonymousUser) + .anonymousUser() Assert.assertNotNull(result) - Assert.assertEquals("eOS@murena.io", result.email) + Assert.assertEquals(testEmailAddress, result.email) } @Test fun testOnFailureReturnErrorWithException() = runTest { - Mockito.`when`(anonymousUser.requestAuthData(testAnonymousRequestBodyData)) - .thenReturn( - NetworkResult.Error( - exception = testFailureException, - code = 1, - errorMessage = loginFailureMessage - ) + Mockito.`when`( + anonymousUser.requestAuthData(testAnonymousRequestData) + ).thenReturn( + NetworkResult.Error( + exception = testFailureException, + code = 1, + errorMessage = loginFailureMessage ) + ) runCatching { - LoginRepositoryImpl(anonymousUser, instrumentationContext) - .run { anonymousUser(testAnonymousRequestBodyData) } + LoginRepositoryImpl(context, testAnonymousRequestData.properties, anonymousUser) + .run { anonymousUser() } }.onFailure { error -> Assert.assertEquals(testFailureException.message, error.message) } -- GitLab From e4219815da5875b4ffa833e198d3ad05fe687f51 Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Sat, 19 Aug 2023 23:00:33 +0530 Subject: [PATCH 11/13] Return flow from usecases to handle all emit on ui --- .../e/apps/domain/login/usecase/UserLoginUseCase.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 33cee4402..359d42bee 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 @@ -21,15 +21,15 @@ package foundation.e.apps.domain.login.usecase 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 import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.single import javax.inject.Inject class UserLoginUseCase @Inject constructor( private val loginRepository: LoginRepository, ) { - suspend fun anonymousUser(): Resource = flow { + fun anonymousUser(): Flow> = flow { try { emit(Resource.Loading) val userResponse = loginRepository.anonymousUser() @@ -37,5 +37,5 @@ class UserLoginUseCase @Inject constructor( } catch (e: Exception) { emit(Resource.Error(e.localizedMessage)) } - }.single() + } } -- GitLab From 9dce99b567b059daab5f2cf746788f8de8d1a66f Mon Sep 17 00:00:00 2001 From: Nishant Dande Date: Mon, 21 Aug 2023 23:45:00 +0530 Subject: [PATCH 12/13] 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 13/13] 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