From b29870c90c942dcd2699c6a41cd972668e444c40 Mon Sep 17 00:00:00 2001 From: Gergely Hegedus Date: Mon, 24 Jan 2022 17:35:45 +0200 Subject: [PATCH 1/2] Issue#31 Remove hilt completely --- app/build.gradle | 57 +--- .../AndroidTestServerTypeConfiguration.kt | 0 .../AndroidTestServerTypeConfiguration.kt | 14 - .../testutils/configuration/HiltTestRunner.kt | 12 - .../configuration/HttpsConfigurationModule.kt | 33 --- app/src/hilt/AndroidManifest.xml | 22 -- .../test/showcase/TestShowcaseApplication.kt | 7 - .../org/fnives/test/showcase/di/AppModule.kt | 52 ---- .../test/showcase/ui/IntentCoordinator.kt | 14 - .../test/showcase/ui/ViewModelDelegate.kt | 12 - .../test/showcase/ui/auth/HiltAuthActivity.kt | 12 - .../test/showcase/ui/home/HiltMainActivity.kt | 12 - .../showcase/ui/splash/HiltSplashActivity.kt | 8 - app/src/koin/AndroidManifest.xml | 21 -- app/src/main/AndroidManifest.xml | 14 +- .../test/showcase/TestShowcaseApplication.kt | 0 .../test/showcase/di/createAppModules.kt | 0 .../session/SessionExpirationListenerImpl.kt | 7 +- .../FavouriteContentLocalStorageImpl.kt | 3 +- .../test/showcase/ui/IntentCoordinator.kt | 0 .../test/showcase/ui/ViewModelDelegate.kt | 0 .../test/showcase/ui/auth/AuthViewModel.kt | 5 +- .../test/showcase/ui/home/MainViewModel.kt | 6 +- .../showcase/ui/splash/SplashViewModel.kt | 5 +- app/src/main/res/values/strings.xml | 1 + .../FavouriteContentLocalStorageImplTest.kt | 0 .../FavouriteContentLocalStorageImplTest.kt | 101 ------- .../test/showcase/robolectric.properties | 4 - .../ReloadKoinModulesIfNecessaryTestRule.kt | 0 .../idling/NetworkSynchronization.kt | 0 .../statesetup/SetupAuthenticationState.kt | 7 +- .../fnives/test/showcase/ui/home/HomeRobot.kt | 8 +- .../test/showcase/ui/home/MainActivityTest.kt | 0 .../showcase/ui/login/AuthActivityTest.kt | 0 .../test/showcase/ui/login/LoginRobot.kt | 8 +- .../showcase/ui/splash/SplashActivityTest.kt | 0 .../test/showcase/ui/splash/SplashRobot.kt | 15 +- .../idling/NetworkSynchronization.kt | 41 --- .../test/showcase/ui/ActivityClassHolder.kt | 14 - .../test/showcase/ui/home/MainActivityTest.kt | 251 ------------------ .../showcase/ui/login/AuthActivityTest.kt | 170 ------------ .../showcase/ui/splash/SplashActivityTest.kt | 120 --------- .../test/showcase/ui/ActivityClassHolder.kt | 14 - .../org/fnives/test/showcase/di/DITest.kt | 0 build.gradle | 17 +- core/build.gradle | 7 - .../content/AddContentToFavouriteUseCase.kt | 3 +- .../core/content/ContentRepository.kt | 3 +- .../core/content/FetchContentUseCase.kt | 4 +- .../core/content/GetAllContentUseCase.kt | 3 +- .../RemoveContentFromFavouritesUseCase.kt | 3 +- .../core/di/{koin => }/createCoreModule.kt | 4 +- .../test/showcase/core/di/hilt/CoreModule.kt | 33 --- .../core/di/hilt/LoggedInModuleInject.kt | 8 - .../core/login/IsUserLoggedInUseCase.kt | 3 +- .../test/showcase/core/login/LoginUseCase.kt | 3 +- .../test/showcase/core/login/LogoutUseCase.kt | 11 +- .../core/session/SessionExpirationAdapter.kt | 3 +- .../NetworkSessionLocalStorageAdapter.kt | 3 +- .../login/{koin => }/LogoutUseCaseTest.kt | 5 +- .../core/login/hilt/LogoutUseCaseTest.kt | 62 ----- .../core/login/hilt/TestCoreComponent.kt | 36 --- gradlescripts/versions.gradle | 1 - .../showcase/hilt/SessionLessQualifier.kt | 6 - .../test/showcase/hilt/SessionQualifier.kt | 6 - network/build.gradle | 5 - .../network/auth/LoginErrorConverter.kt | 3 +- .../network/auth/LoginRemoteSourceImpl.kt | 3 +- .../content/ContentRemoteSourceImpl.kt | 3 +- .../di/{koin => }/createNetworkmodules.kt | 3 +- .../network/di/hilt/BindsBaseOkHttpClient.kt | 17 -- .../network/di/hilt/HiltNetworkModule.kt | 96 ------- .../session/AuthenticationHeaderUtils.kt | 3 +- .../network/session/SessionAuthenticator.kt | 3 +- .../showcase/network/TestNetworkComponent.kt | 44 --- .../LoginRemoteSourceRefreshActionImplTest.kt | 5 +- .../auth/{koin => }/LoginRemoteSourceTest.kt | 5 +- .../LoginRemoteSourceRefreshActionImplTest.kt | 103 ------- .../auth/hilt/LoginRemoteSourceTest.kt | 120 --------- .../content/CodeKataSessionExpirationTest.kt | 2 +- .../{koin => }/ContentRemoteSourceImplTest.kt | 5 +- .../{koin => }/SessionExpirationTest.kt | 5 +- .../hilt/ContentRemoteSourceImplTest.kt | 121 --------- .../content/hilt/SessionExpirationTest.kt | 110 -------- 84 files changed, 75 insertions(+), 1875 deletions(-) rename app/src/{androidTestKoin => androidTest}/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt (100%) delete mode 100644 app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt delete mode 100644 app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/HiltTestRunner.kt delete mode 100644 app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/HttpsConfigurationModule.kt delete mode 100644 app/src/hilt/AndroidManifest.xml delete mode 100644 app/src/hilt/java/org/fnives/test/showcase/TestShowcaseApplication.kt delete mode 100644 app/src/hilt/java/org/fnives/test/showcase/di/AppModule.kt delete mode 100644 app/src/hilt/java/org/fnives/test/showcase/ui/IntentCoordinator.kt delete mode 100644 app/src/hilt/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt delete mode 100644 app/src/hilt/java/org/fnives/test/showcase/ui/auth/HiltAuthActivity.kt delete mode 100644 app/src/hilt/java/org/fnives/test/showcase/ui/home/HiltMainActivity.kt delete mode 100644 app/src/hilt/java/org/fnives/test/showcase/ui/splash/HiltSplashActivity.kt delete mode 100644 app/src/koin/AndroidManifest.xml rename app/src/{koin => main}/java/org/fnives/test/showcase/TestShowcaseApplication.kt (100%) rename app/src/{koin => main}/java/org/fnives/test/showcase/di/createAppModules.kt (100%) rename app/src/{koin => main}/java/org/fnives/test/showcase/ui/IntentCoordinator.kt (100%) rename app/src/{koin => main}/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt (100%) rename app/src/{robolectricTestKoin/java/org/fnives/test/showcase => robolectricTest/java/org/fnives/test/showcase/testutils}/favourite/FavouriteContentLocalStorageImplTest.kt (100%) delete mode 100644 app/src/robolectricTestHilt/java/org/fnives/test/showcase/favourite/FavouriteContentLocalStorageImplTest.kt delete mode 100644 app/src/robolectricTestHilt/resources/org/fnives/test/showcase/robolectric.properties rename app/src/{sharedTestKoin => sharedTest}/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt (100%) rename app/src/{sharedTestKoin => sharedTest}/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt (100%) rename app/src/{sharedTestKoin => sharedTest}/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt (100%) rename app/src/{sharedTestKoin => sharedTest}/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt (100%) rename app/src/{sharedTestKoin => sharedTest}/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt (100%) delete mode 100644 app/src/sharedTestHilt/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt delete mode 100644 app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/ActivityClassHolder.kt delete mode 100644 app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt delete mode 100644 app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt delete mode 100644 app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt delete mode 100644 app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/ActivityClassHolder.kt rename app/src/{testKoin => test}/java/org/fnives/test/showcase/di/DITest.kt (100%) rename core/src/main/java/org/fnives/test/showcase/core/di/{koin => }/createCoreModule.kt (95%) delete mode 100644 core/src/main/java/org/fnives/test/showcase/core/di/hilt/CoreModule.kt delete mode 100644 core/src/main/java/org/fnives/test/showcase/core/di/hilt/LoggedInModuleInject.kt rename core/src/test/java/org/fnives/test/showcase/core/login/{koin => }/LogoutUseCaseTest.kt (93%) delete mode 100644 core/src/test/java/org/fnives/test/showcase/core/login/hilt/LogoutUseCaseTest.kt delete mode 100644 core/src/test/java/org/fnives/test/showcase/core/login/hilt/TestCoreComponent.kt delete mode 100644 model/src/main/java/org/fnives/test/showcase/hilt/SessionLessQualifier.kt delete mode 100644 model/src/main/java/org/fnives/test/showcase/hilt/SessionQualifier.kt rename network/src/main/java/org/fnives/test/showcase/network/di/{koin => }/createNetworkmodules.kt (97%) delete mode 100644 network/src/main/java/org/fnives/test/showcase/network/di/hilt/BindsBaseOkHttpClient.kt delete mode 100644 network/src/main/java/org/fnives/test/showcase/network/di/hilt/HiltNetworkModule.kt delete mode 100644 network/src/test/java/org/fnives/test/showcase/network/TestNetworkComponent.kt rename network/src/test/java/org/fnives/test/showcase/network/auth/{koin => }/LoginRemoteSourceRefreshActionImplTest.kt (96%) rename network/src/test/java/org/fnives/test/showcase/network/auth/{koin => }/LoginRemoteSourceTest.kt (96%) delete mode 100644 network/src/test/java/org/fnives/test/showcase/network/auth/hilt/LoginRemoteSourceRefreshActionImplTest.kt delete mode 100644 network/src/test/java/org/fnives/test/showcase/network/auth/hilt/LoginRemoteSourceTest.kt rename network/src/test/java/org/fnives/test/showcase/network/content/{koin => }/ContentRemoteSourceImplTest.kt (96%) rename network/src/test/java/org/fnives/test/showcase/network/content/{koin => }/SessionExpirationTest.kt (96%) delete mode 100644 network/src/test/java/org/fnives/test/showcase/network/content/hilt/ContentRemoteSourceImplTest.kt delete mode 100644 network/src/test/java/org/fnives/test/showcase/network/content/hilt/SessionExpirationTest.kt diff --git a/app/build.gradle b/app/build.gradle index f461865..163f056 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -2,8 +2,6 @@ plugins { id 'com.android.application' id 'kotlin-android' id 'kotlin-kapt' - // hilt specific - id 'dagger.hilt.android.plugin' } android { @@ -33,19 +31,6 @@ android { } } flavorDimensions 'di' - productFlavors { - hilt { - dimension 'di' - resValue "string", "app_name", "Hilt Test-ShowCase" - applicationId "org.fnives.test.showcase.hilt" - testInstrumentationRunner "org.fnives.test.showcase.testutils.configuration.HiltTestRunner" - } - koin { - dimension 'di' - resValue "string", "app_name", "Koin Test-ShowCase" - applicationId "org.fnives.test.showcase.koin" - } - } buildFeatures { viewBinding true @@ -56,29 +41,11 @@ android { java.srcDirs += "src/sharedTest/java" assets.srcDirs += files("$projectDir/schemas".toString()) } - androidTestHilt { - java.srcDirs += "src/sharedTestHilt/java" - assets.srcDirs += files("$projectDir/schemas".toString()) - } - androidTestKoin { - java.srcDirs += "src/sharedTestKoin/java" - assets.srcDirs += files("$projectDir/schemas".toString()) - } - test { java.srcDirs += "src/sharedTest/java" java.srcDirs += "src/robolectricTest/java" resources.srcDirs += files("$projectDir/schemas".toString()) } - testHilt { - java.srcDirs += "src/sharedTestHilt/java" - java.srcDirs += "src/robolectricTestHilt/java" - resources.srcDirs += "src/robolectricTestHilt/resources" - } - testKoin { - java.srcDirs += "src/sharedTestKoin/java" - java.srcDirs += "src/robolectricTestKoin/java" - } } // needed for androidTest @@ -90,17 +57,10 @@ android { } } -hilt { - enableAggregatingTask = true - enableExperimentalClasspathAggregation = true -} - afterEvaluate { // making sure the :mockserver is assembled after :clean when running tests - testKoinDebugUnitTest.dependsOn tasks.getByPath(':mockserver:assemble') - testKoinReleaseUnitTest.dependsOn tasks.getByPath(':mockserver:assemble') - testHiltDebugUnitTest.dependsOn tasks.getByPath(':mockserver:assemble') - testHiltReleaseUnitTest.dependsOn tasks.getByPath(':mockserver:assemble') + testDebugUnitTest.dependsOn tasks.getByPath(':mockserver:assemble') + testReleaseUnitTest.dependsOn tasks.getByPath(':mockserver:assemble') } dependencies { @@ -113,13 +73,7 @@ dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$androidx_livedata_version" implementation "androidx.swiperefreshlayout:swiperefreshlayout:$androidx_swiperefreshlayout_version" - // Koin - koinImplementation "io.insert-koin:koin-android:$koin_version" - - // Hilt - implementation "com.google.dagger:hilt-android:$hilt_version" - kaptHilt "com.google.dagger:hilt-compiler:$hilt_version" - hiltImplementation "androidx.activity:activity-ktx:$activity_ktx_version" + implementation "io.insert-koin:koin-android:$koin_version" implementation "androidx.room:room-runtime:$androidx_room_version" kapt "androidx.room:room-compiler:$androidx_room_version" @@ -151,8 +105,6 @@ dependencies { testImplementation project(':mockserver') testImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version" testRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version" - testImplementation "com.google.dagger:hilt-android-testing:$hilt_version" - kaptTest "com.google.dagger:hilt-compiler:$hilt_version" androidTestImplementation "androidx.room:room-testing:$androidx_room_version" androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" @@ -167,9 +119,6 @@ dependencies { androidTestImplementation project(':mockserver') androidTestImplementation "androidx.arch.core:core-testing:$testing_androidx_arch_core_version" androidTestRuntimeOnly "org.junit.vintage:junit-vintage-engine:$testing_junit5_version" - androidTestImplementation "com.google.dagger:hilt-android-testing:$hilt_version" - kaptAndroidTest "com.google.dagger:hilt-compiler:$hilt_version" - androidTestImplementation project(":network") // hilt needs it implementation "io.reactivex.rxjava3:rxjava:3.1.3" } diff --git a/app/src/androidTestKoin/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt b/app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt similarity index 100% rename from app/src/androidTestKoin/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt rename to app/src/androidTest/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt diff --git a/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt b/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt deleted file mode 100644 index f538425..0000000 --- a/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/AndroidTestServerTypeConfiguration.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.fnives.test.showcase.testutils.configuration - -import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup - -object AndroidTestServerTypeConfiguration : ServerTypeConfiguration { - override val useHttps: Boolean get() = true - - override val url: String get() = "${MockServerScenarioSetup.HTTPS_BASE_URL}:${MockServerScenarioSetup.PORT}/" - - override fun invoke(mockServerScenarioSetup: MockServerScenarioSetup) { - val handshakeCertificates = mockServerScenarioSetup.clientCertificates ?: return - HttpsConfigurationModule.handshakeCertificates = handshakeCertificates - } -} diff --git a/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/HiltTestRunner.kt b/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/HiltTestRunner.kt deleted file mode 100644 index d2b4ee5..0000000 --- a/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/HiltTestRunner.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.fnives.test.showcase.testutils.configuration - -import android.app.Application -import android.content.Context -import androidx.test.runner.AndroidJUnitRunner -import dagger.hilt.android.testing.HiltTestApplication - -class HiltTestRunner : AndroidJUnitRunner() { - - override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application = - super.newApplication(cl, HiltTestApplication::class.java.name, context) -} diff --git a/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/HttpsConfigurationModule.kt b/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/HttpsConfigurationModule.kt deleted file mode 100644 index 3bf93c8..0000000 --- a/app/src/androidTestHilt/java/org/fnives/test/showcase/testutils/configuration/HttpsConfigurationModule.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.fnives.test.showcase.testutils.configuration - -import dagger.Module -import dagger.Provides -import dagger.hilt.components.SingletonComponent -import dagger.hilt.testing.TestInstallIn -import okhttp3.tls.HandshakeCertificates -import org.fnives.test.showcase.hilt.SessionLessQualifier -import org.fnives.test.showcase.network.di.hilt.BindsBaseOkHttpClient -import org.fnives.test.showcase.network.di.hilt.HiltNetworkModule -import javax.inject.Singleton - -@Module -@TestInstallIn( - components = [SingletonComponent::class], - replaces = [BindsBaseOkHttpClient::class] -) -object HttpsConfigurationModule { - - lateinit var handshakeCertificates: HandshakeCertificates - - @Provides - @Singleton - @SessionLessQualifier - fun bindsBaseOkHttpClient(enableLogging: Boolean) = - HiltNetworkModule.provideSessionLessOkHttpClient(enableLogging) - .newBuilder() - .sslSocketFactory( - handshakeCertificates.sslSocketFactory(), - handshakeCertificates.trustManager - ) - .build() -} diff --git a/app/src/hilt/AndroidManifest.xml b/app/src/hilt/AndroidManifest.xml deleted file mode 100644 index d65911d..0000000 --- a/app/src/hilt/AndroidManifest.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/hilt/java/org/fnives/test/showcase/TestShowcaseApplication.kt b/app/src/hilt/java/org/fnives/test/showcase/TestShowcaseApplication.kt deleted file mode 100644 index 4881f5c..0000000 --- a/app/src/hilt/java/org/fnives/test/showcase/TestShowcaseApplication.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.fnives.test.showcase - -import android.app.Application -import dagger.hilt.android.HiltAndroidApp - -@HiltAndroidApp -class TestShowcaseApplication : Application() diff --git a/app/src/hilt/java/org/fnives/test/showcase/di/AppModule.kt b/app/src/hilt/java/org/fnives/test/showcase/di/AppModule.kt deleted file mode 100644 index 3e574ee..0000000 --- a/app/src/hilt/java/org/fnives/test/showcase/di/AppModule.kt +++ /dev/null @@ -1,52 +0,0 @@ -package org.fnives.test.showcase.di - -import android.content.Context -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import org.fnives.test.showcase.core.session.SessionExpirationListener -import org.fnives.test.showcase.core.storage.UserDataLocalStorage -import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage -import org.fnives.test.showcase.session.SessionExpirationListenerImpl -import org.fnives.test.showcase.storage.SharedPreferencesManagerImpl -import org.fnives.test.showcase.storage.database.DatabaseInitialization -import org.fnives.test.showcase.storage.favourite.FavouriteContentLocalStorageImpl -import javax.inject.Singleton - -@InstallIn(SingletonComponent::class) -@Module -object AppModule { - - @Provides - fun provideBaseUrl(): String = BaseUrlProvider.get().baseUrl - - @Provides - fun enableLogging(): Boolean = true - - @Singleton - @Provides - fun provideFavouriteDao(@ApplicationContext context: Context) = - DatabaseInitialization.create(context).favouriteDao - - @Provides - fun provideSharedPreferencesManagerImpl(@ApplicationContext context: Context) = - SharedPreferencesManagerImpl.create(context) - - @Singleton - @Provides - fun provideUserDataLocalStorage( - sharedPreferencesManagerImpl: SharedPreferencesManagerImpl - ): UserDataLocalStorage = sharedPreferencesManagerImpl - - @Provides - fun provideFavouriteContentLocalStorage( - favouriteContentLocalStorageImpl: FavouriteContentLocalStorageImpl - ): FavouriteContentLocalStorage = favouriteContentLocalStorageImpl - - @Provides - internal fun bindSessionExpirationListener( - sessionExpirationListenerImpl: SessionExpirationListenerImpl - ): SessionExpirationListener = sessionExpirationListenerImpl -} diff --git a/app/src/hilt/java/org/fnives/test/showcase/ui/IntentCoordinator.kt b/app/src/hilt/java/org/fnives/test/showcase/ui/IntentCoordinator.kt deleted file mode 100644 index 2abf987..0000000 --- a/app/src/hilt/java/org/fnives/test/showcase/ui/IntentCoordinator.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.fnives.test.showcase.ui - -import android.content.Context -import org.fnives.test.showcase.ui.auth.HiltAuthActivity -import org.fnives.test.showcase.ui.home.HiltMainActivity - -object IntentCoordinator { - - fun mainActivitygetStartIntent(context: Context) = - HiltMainActivity.getStartIntent(context) - - fun authActivitygetStartIntent(context: Context) = - HiltAuthActivity.getStartIntent(context) -} diff --git a/app/src/hilt/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt b/app/src/hilt/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt deleted file mode 100644 index 7ef6742..0000000 --- a/app/src/hilt/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.fnives.test.showcase.ui - -import androidx.activity.ComponentActivity -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelStoreOwner -import androidx.activity.viewModels as androidxViewModel - -inline fun ViewModelStoreOwner.viewModels(): Lazy = - when (this) { - is ComponentActivity -> androidxViewModel() - else -> throw IllegalStateException("Only supports activity viewModel for now") - } diff --git a/app/src/hilt/java/org/fnives/test/showcase/ui/auth/HiltAuthActivity.kt b/app/src/hilt/java/org/fnives/test/showcase/ui/auth/HiltAuthActivity.kt deleted file mode 100644 index 2574965..0000000 --- a/app/src/hilt/java/org/fnives/test/showcase/ui/auth/HiltAuthActivity.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.fnives.test.showcase.ui.auth - -import android.content.Context -import android.content.Intent -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class HiltAuthActivity : AuthActivity() { - companion object { - fun getStartIntent(context: Context): Intent = Intent(context, HiltAuthActivity::class.java) - } -} diff --git a/app/src/hilt/java/org/fnives/test/showcase/ui/home/HiltMainActivity.kt b/app/src/hilt/java/org/fnives/test/showcase/ui/home/HiltMainActivity.kt deleted file mode 100644 index 94b0b5f..0000000 --- a/app/src/hilt/java/org/fnives/test/showcase/ui/home/HiltMainActivity.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.fnives.test.showcase.ui.home - -import android.content.Context -import android.content.Intent -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class HiltMainActivity : MainActivity() { - companion object { - fun getStartIntent(context: Context): Intent = Intent(context, HiltMainActivity::class.java) - } -} diff --git a/app/src/hilt/java/org/fnives/test/showcase/ui/splash/HiltSplashActivity.kt b/app/src/hilt/java/org/fnives/test/showcase/ui/splash/HiltSplashActivity.kt deleted file mode 100644 index d6b6f2b..0000000 --- a/app/src/hilt/java/org/fnives/test/showcase/ui/splash/HiltSplashActivity.kt +++ /dev/null @@ -1,8 +0,0 @@ -package org.fnives.test.showcase.ui.splash - -import android.annotation.SuppressLint -import dagger.hilt.android.AndroidEntryPoint - -@SuppressLint("CustomSplashScreen") -@AndroidEntryPoint -class HiltSplashActivity : SplashActivity() diff --git a/app/src/koin/AndroidManifest.xml b/app/src/koin/AndroidManifest.xml deleted file mode 100644 index 72cf478..0000000 --- a/app/src/koin/AndroidManifest.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f778c8e..f64d7bd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,6 +13,18 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.TestShowCase" - tools:ignore="AllowBackup"/> + tools:ignore="AllowBackup"> + + + + + + + + + + \ No newline at end of file diff --git a/app/src/koin/java/org/fnives/test/showcase/TestShowcaseApplication.kt b/app/src/main/java/org/fnives/test/showcase/TestShowcaseApplication.kt similarity index 100% rename from app/src/koin/java/org/fnives/test/showcase/TestShowcaseApplication.kt rename to app/src/main/java/org/fnives/test/showcase/TestShowcaseApplication.kt diff --git a/app/src/koin/java/org/fnives/test/showcase/di/createAppModules.kt b/app/src/main/java/org/fnives/test/showcase/di/createAppModules.kt similarity index 100% rename from app/src/koin/java/org/fnives/test/showcase/di/createAppModules.kt rename to app/src/main/java/org/fnives/test/showcase/di/createAppModules.kt diff --git a/app/src/main/java/org/fnives/test/showcase/session/SessionExpirationListenerImpl.kt b/app/src/main/java/org/fnives/test/showcase/session/SessionExpirationListenerImpl.kt index b0fb00d..cd80718 100644 --- a/app/src/main/java/org/fnives/test/showcase/session/SessionExpirationListenerImpl.kt +++ b/app/src/main/java/org/fnives/test/showcase/session/SessionExpirationListenerImpl.kt @@ -4,15 +4,10 @@ import android.content.Context import android.content.Intent import android.os.Handler import android.os.Looper -import dagger.hilt.android.qualifiers.ApplicationContext import org.fnives.test.showcase.core.session.SessionExpirationListener import org.fnives.test.showcase.ui.IntentCoordinator -import javax.inject.Inject -class SessionExpirationListenerImpl @Inject constructor( - @ApplicationContext - private val context: Context -) : SessionExpirationListener { +class SessionExpirationListenerImpl(private val context: Context) : SessionExpirationListener { override fun onSessionExpired() { Handler(Looper.getMainLooper()).post { diff --git a/app/src/main/java/org/fnives/test/showcase/storage/favourite/FavouriteContentLocalStorageImpl.kt b/app/src/main/java/org/fnives/test/showcase/storage/favourite/FavouriteContentLocalStorageImpl.kt index f93416a..14834df 100644 --- a/app/src/main/java/org/fnives/test/showcase/storage/favourite/FavouriteContentLocalStorageImpl.kt +++ b/app/src/main/java/org/fnives/test/showcase/storage/favourite/FavouriteContentLocalStorageImpl.kt @@ -4,9 +4,8 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage import org.fnives.test.showcase.model.content.ContentId -import javax.inject.Inject -class FavouriteContentLocalStorageImpl @Inject constructor( +class FavouriteContentLocalStorageImpl( private val favouriteDao: FavouriteDao ) : FavouriteContentLocalStorage { diff --git a/app/src/koin/java/org/fnives/test/showcase/ui/IntentCoordinator.kt b/app/src/main/java/org/fnives/test/showcase/ui/IntentCoordinator.kt similarity index 100% rename from app/src/koin/java/org/fnives/test/showcase/ui/IntentCoordinator.kt rename to app/src/main/java/org/fnives/test/showcase/ui/IntentCoordinator.kt diff --git a/app/src/koin/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt b/app/src/main/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt similarity index 100% rename from app/src/koin/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt rename to app/src/main/java/org/fnives/test/showcase/ui/ViewModelDelegate.kt diff --git a/app/src/main/java/org/fnives/test/showcase/ui/auth/AuthViewModel.kt b/app/src/main/java/org/fnives/test/showcase/ui/auth/AuthViewModel.kt index b5fa26f..0221f14 100644 --- a/app/src/main/java/org/fnives/test/showcase/ui/auth/AuthViewModel.kt +++ b/app/src/main/java/org/fnives/test/showcase/ui/auth/AuthViewModel.kt @@ -4,17 +4,14 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import org.fnives.test.showcase.core.login.LoginUseCase import org.fnives.test.showcase.model.auth.LoginCredentials import org.fnives.test.showcase.model.auth.LoginStatus import org.fnives.test.showcase.model.shared.Answer import org.fnives.test.showcase.ui.shared.Event -import javax.inject.Inject -@HiltViewModel -class AuthViewModel @Inject constructor(private val loginUseCase: LoginUseCase) : ViewModel() { +class AuthViewModel(private val loginUseCase: LoginUseCase) : ViewModel() { private val _username = MutableLiveData() val username: LiveData = _username diff --git a/app/src/main/java/org/fnives/test/showcase/ui/home/MainViewModel.kt b/app/src/main/java/org/fnives/test/showcase/ui/home/MainViewModel.kt index 14e49fe..f78e124 100644 --- a/app/src/main/java/org/fnives/test/showcase/ui/home/MainViewModel.kt +++ b/app/src/main/java/org/fnives/test/showcase/ui/home/MainViewModel.kt @@ -6,8 +6,6 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.distinctUntilChanged import androidx.lifecycle.liveData import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import org.fnives.test.showcase.core.content.AddContentToFavouriteUseCase import org.fnives.test.showcase.core.content.FetchContentUseCase @@ -18,10 +16,8 @@ import org.fnives.test.showcase.model.content.ContentId import org.fnives.test.showcase.model.content.FavouriteContent import org.fnives.test.showcase.model.shared.Resource import org.fnives.test.showcase.ui.shared.Event -import javax.inject.Inject -@HiltViewModel -class MainViewModel @Inject constructor( +class MainViewModel( private val getAllContentUseCase: GetAllContentUseCase, private val logoutUseCase: LogoutUseCase, private val fetchContentUseCase: FetchContentUseCase, diff --git a/app/src/main/java/org/fnives/test/showcase/ui/splash/SplashViewModel.kt b/app/src/main/java/org/fnives/test/showcase/ui/splash/SplashViewModel.kt index 13a1887..d9bbd43 100644 --- a/app/src/main/java/org/fnives/test/showcase/ui/splash/SplashViewModel.kt +++ b/app/src/main/java/org/fnives/test/showcase/ui/splash/SplashViewModel.kt @@ -4,15 +4,12 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.fnives.test.showcase.core.login.IsUserLoggedInUseCase import org.fnives.test.showcase.ui.shared.Event -import javax.inject.Inject -@HiltViewModel -class SplashViewModel @Inject constructor(isUserLoggedInUseCase: IsUserLoggedInUseCase) : ViewModel() { +class SplashViewModel(isUserLoggedInUseCase: IsUserLoggedInUseCase) : ViewModel() { private val _navigateTo = MutableLiveData>() val navigateTo: LiveData> = _navigateTo diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 40bb924..f84909a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,4 +1,5 @@ + Test ShowCase Login Username Password diff --git a/app/src/robolectricTestKoin/java/org/fnives/test/showcase/favourite/FavouriteContentLocalStorageImplTest.kt b/app/src/robolectricTest/java/org/fnives/test/showcase/testutils/favourite/FavouriteContentLocalStorageImplTest.kt similarity index 100% rename from app/src/robolectricTestKoin/java/org/fnives/test/showcase/favourite/FavouriteContentLocalStorageImplTest.kt rename to app/src/robolectricTest/java/org/fnives/test/showcase/testutils/favourite/FavouriteContentLocalStorageImplTest.kt diff --git a/app/src/robolectricTestHilt/java/org/fnives/test/showcase/favourite/FavouriteContentLocalStorageImplTest.kt b/app/src/robolectricTestHilt/java/org/fnives/test/showcase/favourite/FavouriteContentLocalStorageImplTest.kt deleted file mode 100644 index d67dd1b..0000000 --- a/app/src/robolectricTestHilt/java/org/fnives/test/showcase/favourite/FavouriteContentLocalStorageImplTest.kt +++ /dev/null @@ -1,101 +0,0 @@ -package org.fnives.test.showcase.favourite - -import androidx.test.ext.junit.runners.AndroidJUnit4 -import dagger.hilt.android.testing.HiltAndroidRule -import dagger.hilt.android.testing.HiltAndroidTest -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.async -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.take -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.test.StandardTestDispatcher -import kotlinx.coroutines.test.TestCoroutineScheduler -import kotlinx.coroutines.test.TestDispatcher -import kotlinx.coroutines.test.advanceUntilIdle -import kotlinx.coroutines.test.runTest -import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage -import org.fnives.test.showcase.model.content.ContentId -import org.fnives.test.showcase.storage.database.DatabaseInitialization -import org.junit.Assert -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import javax.inject.Inject - -@Suppress("TestFunctionName") -@OptIn(ExperimentalCoroutinesApi::class) -@RunWith(AndroidJUnit4::class) -@HiltAndroidTest -internal class FavouriteContentLocalStorageImplTest { - - @get:Rule - val hiltRule = HiltAndroidRule(this) - - @Inject - lateinit var sut: FavouriteContentLocalStorage - private lateinit var testDispatcher: TestDispatcher - - @Before - fun setUp() { - testDispatcher = StandardTestDispatcher(TestCoroutineScheduler()) - DatabaseInitialization.dispatcher = testDispatcher - hiltRule.inject() - } - - /** GIVEN content_id WHEN added to Favourite THEN it can be read out */ - @Test - fun addingContentIdToFavouriteCanBeLaterReadOut() = runTest(testDispatcher) { - val expected = listOf(ContentId("a")) - - sut.markAsFavourite(ContentId("a")) - val actual = sut.observeFavourites().first() - - Assert.assertEquals(expected, actual) - } - - /** GIVEN content_id added WHEN removed to Favourite THEN it no longer can be read out */ - @Test - fun contentIdAddedThenRemovedCanNoLongerBeReadOut() = runTest(testDispatcher) { - val expected = listOf() - sut.markAsFavourite(ContentId("b")) - - sut.deleteAsFavourite(ContentId("b")) - val actual = sut.observeFavourites().first() - - Assert.assertEquals(expected, actual) - } - - /** GIVEN empty database WHILE observing content WHEN favourite added THEN change is emitted */ - @Test - fun addingFavouriteUpdatesExistingObservers() = runTest(testDispatcher) { - val expected = listOf(listOf(), listOf(ContentId("a"))) - - val actual = async(coroutineContext) { - sut.observeFavourites().take(2).toList() - } - advanceUntilIdle() - - sut.markAsFavourite(ContentId("a")) - advanceUntilIdle() - - Assert.assertEquals(expected, actual.getCompleted()) - } - - /** GIVEN non empty database WHILE observing content WHEN favourite removed THEN change is emitted */ - @Test - fun removingFavouriteUpdatesExistingObservers() = runTest(testDispatcher) { - val expected = listOf(listOf(ContentId("a")), listOf()) - sut.markAsFavourite(ContentId("a")) - - val actual = async(coroutineContext) { - sut.observeFavourites().take(2).toList() - } - advanceUntilIdle() - - sut.deleteAsFavourite(ContentId("a")) - advanceUntilIdle() - - Assert.assertEquals(expected, actual.getCompleted()) - } -} diff --git a/app/src/robolectricTestHilt/resources/org/fnives/test/showcase/robolectric.properties b/app/src/robolectricTestHilt/resources/org/fnives/test/showcase/robolectric.properties deleted file mode 100644 index cd922e4..0000000 --- a/app/src/robolectricTestHilt/resources/org/fnives/test/showcase/robolectric.properties +++ /dev/null @@ -1,4 +0,0 @@ -sdk=28 -shadows=org.fnives.test.showcase.testutils.shadow.ShadowSnackbar -instrumentedPackages=androidx.loader.content -application=dagger.hilt.android.testing.HiltTestApplication diff --git a/app/src/sharedTestKoin/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt similarity index 100% rename from app/src/sharedTestKoin/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt rename to app/src/sharedTest/java/org/fnives/test/showcase/testutils/ReloadKoinModulesIfNecessaryTestRule.kt diff --git a/app/src/sharedTestKoin/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt similarity index 100% rename from app/src/sharedTestKoin/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt rename to app/src/sharedTest/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/statesetup/SetupAuthenticationState.kt b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/statesetup/SetupAuthenticationState.kt index a5049ae..a2b2a8b 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/testutils/statesetup/SetupAuthenticationState.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/testutils/statesetup/SetupAuthenticationState.kt @@ -5,8 +5,9 @@ import androidx.test.core.app.ActivityScenario import org.fnives.test.showcase.network.mockserver.MockServerScenarioSetup import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario import org.fnives.test.showcase.testutils.configuration.MainDispatcherTestRule -import org.fnives.test.showcase.ui.ActivityClassHolder +import org.fnives.test.showcase.ui.auth.AuthActivity import org.fnives.test.showcase.ui.home.HomeRobot +import org.fnives.test.showcase.ui.home.MainActivity import org.fnives.test.showcase.ui.login.LoginRobot import org.koin.test.KoinTest @@ -22,7 +23,7 @@ object SetupAuthenticationState : KoinTest { password = "b" ) ) - val activityScenario = ActivityScenario.launch(ActivityClassHolder.authActivity().java) + val activityScenario = ActivityScenario.launch(AuthActivity::class.java) activityScenario.moveToState(Lifecycle.State.RESUMED) val loginRobot = LoginRobot() loginRobot.setupIntentResults() @@ -39,7 +40,7 @@ object SetupAuthenticationState : KoinTest { fun setupLogout( mainDispatcherTestRule: MainDispatcherTestRule ) { - val activityScenario = ActivityScenario.launch(ActivityClassHolder.mainActivity().java) + val activityScenario = ActivityScenario.launch(MainActivity::class.java) activityScenario.moveToState(Lifecycle.State.RESUMED) val homeRobot = HomeRobot() homeRobot diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/HomeRobot.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/HomeRobot.kt index 8a9f398..c13ef6b 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/HomeRobot.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/HomeRobot.kt @@ -26,14 +26,14 @@ import org.fnives.test.showcase.testutils.statesetup.SetupAuthenticationState import org.fnives.test.showcase.testutils.viewactions.PullToRefresh import org.fnives.test.showcase.testutils.viewactions.WithDrawable import org.fnives.test.showcase.testutils.viewactions.notIntended -import org.fnives.test.showcase.ui.ActivityClassHolder +import org.fnives.test.showcase.ui.auth.AuthActivity import org.hamcrest.Matchers.allOf class HomeRobot : Robot { override fun init() { Intents.init() - Intents.intending(IntentMatchers.hasComponent(ActivityClassHolder.authActivity().java.canonicalName)) + Intents.intending(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName)) .respondWith(Instrumentation.ActivityResult(0, null)) } @@ -42,11 +42,11 @@ class HomeRobot : Robot { } fun assertNavigatedToAuth() = apply { - Intents.intended(IntentMatchers.hasComponent(ActivityClassHolder.authActivity().java.canonicalName)) + Intents.intended(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName)) } fun assertDidNotNavigateToAuth() = apply { - notIntended(IntentMatchers.hasComponent(ActivityClassHolder.authActivity().java.canonicalName)) + notIntended(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName)) } fun clickSignOut() = apply { diff --git a/app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt similarity index 100% rename from app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt rename to app/src/sharedTest/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt diff --git a/app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt similarity index 100% rename from app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt rename to app/src/sharedTest/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/LoginRobot.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/LoginRobot.kt index b00b62a..4e8aba6 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/LoginRobot.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/ui/login/LoginRobot.kt @@ -21,7 +21,7 @@ import org.fnives.test.showcase.testutils.configuration.SpecificTestConfiguratio import org.fnives.test.showcase.testutils.configuration.TestConfigurationsFactory import org.fnives.test.showcase.testutils.robot.Robot import org.fnives.test.showcase.testutils.viewactions.notIntended -import org.fnives.test.showcase.ui.ActivityClassHolder +import org.fnives.test.showcase.ui.home.MainActivity import org.hamcrest.core.IsNot.not class LoginRobot( @@ -41,7 +41,7 @@ class LoginRobot( } fun setupIntentResults() { - intending(hasComponent(ActivityClassHolder.mainActivity().java.canonicalName)) + intending(hasComponent(MainActivity::class.java.canonicalName)) .respondWith(Instrumentation.ActivityResult(Activity.RESULT_OK, Intent())) } @@ -95,10 +95,10 @@ class LoginRobot( } fun assertNavigatedToHome() = apply { - intended(hasComponent(ActivityClassHolder.mainActivity().java.canonicalName)) + intended(hasComponent(MainActivity::class.java.canonicalName)) } fun assertNotNavigatedToHome() = apply { - notIntended(hasComponent(ActivityClassHolder.mainActivity().java.canonicalName)) + notIntended(hasComponent(MainActivity::class.java.canonicalName)) } } diff --git a/app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt similarity index 100% rename from app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt rename to app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt diff --git a/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashRobot.kt b/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashRobot.kt index 683203f..5ed4439 100644 --- a/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashRobot.kt +++ b/app/src/sharedTest/java/org/fnives/test/showcase/ui/splash/SplashRobot.kt @@ -8,15 +8,16 @@ import org.fnives.test.showcase.testutils.configuration.MainDispatcherTestRule import org.fnives.test.showcase.testutils.robot.Robot import org.fnives.test.showcase.testutils.statesetup.SetupAuthenticationState import org.fnives.test.showcase.testutils.viewactions.notIntended -import org.fnives.test.showcase.ui.ActivityClassHolder +import org.fnives.test.showcase.ui.auth.AuthActivity +import org.fnives.test.showcase.ui.home.MainActivity class SplashRobot : Robot { override fun init() { Intents.init() - Intents.intending(IntentMatchers.hasComponent(ActivityClassHolder.mainActivity().java.canonicalName)) + Intents.intending(IntentMatchers.hasComponent(MainActivity::class.java.canonicalName)) .respondWith(Instrumentation.ActivityResult(0, null)) - Intents.intending(IntentMatchers.hasComponent(ActivityClassHolder.authActivity().java.canonicalName)) + Intents.intending(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName)) .respondWith(Instrumentation.ActivityResult(0, null)) } @@ -42,18 +43,18 @@ class SplashRobot : Robot { } fun assertHomeIsStarted() = apply { - Intents.intended(IntentMatchers.hasComponent(ActivityClassHolder.mainActivity().java.canonicalName)) + Intents.intended(IntentMatchers.hasComponent(MainActivity::class.java.canonicalName)) } fun assertHomeIsNotStarted() = apply { - notIntended(IntentMatchers.hasComponent(ActivityClassHolder.mainActivity().java.canonicalName)) + notIntended(IntentMatchers.hasComponent(MainActivity::class.java.canonicalName)) } fun assertAuthIsStarted() = apply { - Intents.intended(IntentMatchers.hasComponent(ActivityClassHolder.authActivity().java.canonicalName)) + Intents.intended(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName)) } fun assertAuthIsNotStarted() = apply { - notIntended(IntentMatchers.hasComponent(ActivityClassHolder.authActivity().java.canonicalName)) + notIntended(IntentMatchers.hasComponent(AuthActivity::class.java.canonicalName)) } } diff --git a/app/src/sharedTestHilt/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt b/app/src/sharedTestHilt/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt deleted file mode 100644 index 2a81671..0000000 --- a/app/src/sharedTestHilt/java/org/fnives/test/showcase/testutils/idling/NetworkSynchronization.kt +++ /dev/null @@ -1,41 +0,0 @@ -package org.fnives.test.showcase.testutils.idling - -import androidx.annotation.CheckResult -import androidx.test.espresso.IdlingResource -import okhttp3.OkHttpClient -import org.fnives.test.showcase.hilt.SessionLessQualifier -import org.fnives.test.showcase.hilt.SessionQualifier -import javax.inject.Inject - -class NetworkSynchronization @Inject constructor( - @SessionQualifier - private val sessionOkhttpClient: OkHttpClient, - @SessionLessQualifier - private val sessionlessOkhttpClient: OkHttpClient -) { - - @CheckResult - fun registerNetworkingSynchronization(): Disposable { - val idlingResources = OkHttpClientTypes.values() - .map { it to getOkHttpClient(it) } - .associateBy { it.second.dispatcher } - .values - .map { (key, client) -> client.asIdlingResource(key.qualifier) } - .map(::IdlingResourceDisposable) - - return CompositeDisposable(idlingResources) - } - - private fun getOkHttpClient(type: OkHttpClientTypes): OkHttpClient = - when (type) { - OkHttpClientTypes.SESSION -> sessionOkhttpClient - OkHttpClientTypes.SESSIONLESS -> sessionlessOkhttpClient - } - - private fun OkHttpClient.asIdlingResource(name: String): IdlingResource = - OkHttp3IdlingResource.create(name, this) - - enum class OkHttpClientTypes(val qualifier: String) { - SESSION("SESSION-NETWORKING"), SESSIONLESS("SESSIONLESS-NETWORKING") - } -} diff --git a/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/ActivityClassHolder.kt b/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/ActivityClassHolder.kt deleted file mode 100644 index 5e1aaca..0000000 --- a/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/ActivityClassHolder.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.fnives.test.showcase.ui - -import org.fnives.test.showcase.ui.auth.HiltAuthActivity -import org.fnives.test.showcase.ui.home.HiltMainActivity -import org.fnives.test.showcase.ui.splash.HiltSplashActivity - -object ActivityClassHolder { - - fun authActivity() = HiltAuthActivity::class - - fun mainActivity() = HiltMainActivity::class - - fun splashActivity() = HiltSplashActivity::class -} diff --git a/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt b/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt deleted file mode 100644 index aacaf2b..0000000 --- a/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/home/MainActivityTest.kt +++ /dev/null @@ -1,251 +0,0 @@ -package org.fnives.test.showcase.ui.home - -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import androidx.lifecycle.Lifecycle -import androidx.test.core.app.ActivityScenario -import androidx.test.ext.junit.runners.AndroidJUnit4 -import dagger.hilt.android.testing.HiltAndroidRule -import dagger.hilt.android.testing.HiltAndroidTest -import org.fnives.test.showcase.model.content.FavouriteContent -import org.fnives.test.showcase.network.mockserver.ContentData -import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario -import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario -import org.fnives.test.showcase.testutils.MockServerScenarioSetupTestRule -import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory -import org.fnives.test.showcase.testutils.idling.Disposable -import org.fnives.test.showcase.testutils.idling.NetworkSynchronization -import org.fnives.test.showcase.testutils.idling.loopMainThreadFor -import org.fnives.test.showcase.testutils.idling.loopMainThreadUntilIdleWithIdlingResources -import org.fnives.test.showcase.testutils.robot.RobotTestRule -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import javax.inject.Inject - -@Suppress("TestFunctionName") -@RunWith(AndroidJUnit4::class) -@HiltAndroidTest -class MainActivityTest { - - private lateinit var activityScenario: ActivityScenario - - @Rule - @JvmField - val instantTaskExecutorRule = InstantTaskExecutorRule() - - @Rule - @JvmField - val snackbarVerificationTestRule = SpecificTestConfigurationsFactory.createSnackbarVerification() - - @Rule - @JvmField - val robotRule = RobotTestRule(HomeRobot()) - private val homeRobot get() = robotRule.robot - - @Rule - @JvmField - val mockServerScenarioSetupTestRule = MockServerScenarioSetupTestRule() - - @Rule - @JvmField - val mainDispatcherTestRule = SpecificTestConfigurationsFactory.createMainDispatcherTestRule() - - @Rule - @JvmField - val hiltRule = HiltAndroidRule(this) - - @Inject - lateinit var networkSynchronization: NetworkSynchronization - - private lateinit var disposable: Disposable - - @Before - fun setUp() { - SpecificTestConfigurationsFactory.createServerTypeConfiguration() - .invoke(mockServerScenarioSetupTestRule.mockServerScenarioSetup) - - hiltRule.inject() - disposable = networkSynchronization.registerNetworkingSynchronization() - homeRobot.setupLogin(mainDispatcherTestRule, mockServerScenarioSetupTestRule.mockServerScenarioSetup) - } - - @After - fun tearDown() { - activityScenario.moveToState(Lifecycle.State.DESTROYED) - disposable.dispose() - } - - /** GIVEN initialized MainActivity WHEN signout is clicked THEN user is signed out */ - @Test - fun signOutClickedResultsInNavigation() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario(ContentScenario.Error(false)) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - homeRobot.clickSignOut() - mainDispatcherTestRule.advanceUntilIdleOrActivityIsDestroyed() - - homeRobot.assertNavigatedToAuth() - } - - /** GIVEN success response WHEN data is returned THEN it is shown on the ui */ - @Test - fun successfulDataLoadingShowsTheElementsOnTheUI() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario(ContentScenario.Success(false)) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - ContentData.contentSuccess.forEachIndexed { index, content -> - homeRobot.assertContainsItem(index, FavouriteContent(content, false)) - } - homeRobot.assertDidNotNavigateToAuth() - } - - /** GIVEN success response WHEN item is clicked THEN ui is updated */ - @Test - fun clickingOnListElementUpdatesTheElementsFavouriteState() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario(ContentScenario.Success(false)) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first()) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true) - homeRobot.assertContainsItem(0, expectedItem) - .assertDidNotNavigateToAuth() - } - - /** GIVEN success response WHEN item is clicked THEN ui is updated even if activity is recreated */ - @Test - fun elementFavouritedIsKeptEvenIfActivityIsRecreated() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario(ContentScenario.Success(false)) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first()) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), true) - - activityScenario.moveToState(Lifecycle.State.DESTROYED) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - homeRobot.assertContainsItem(0, expectedItem) - .assertDidNotNavigateToAuth() - } - - /** GIVEN success response WHEN item is clicked then clicked again THEN ui is updated */ - @Test - fun clickingAnElementMultipleTimesProperlyUpdatesIt() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario(ContentScenario.Success(false)) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first()) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - homeRobot.clickOnContentItem(0, ContentData.contentSuccess.first()) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - val expectedItem = FavouriteContent(ContentData.contentSuccess.first(), false) - homeRobot.assertContainsItem(0, expectedItem) - .assertDidNotNavigateToAuth() - } - - /** GIVEN error response WHEN loaded THEN error is Shown */ - @Test - fun networkErrorResultsInUIErrorStateShown() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario(ContentScenario.Error(false)) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - homeRobot.assertContainsNoItems() - .assertContainsError() - .assertDidNotNavigateToAuth() - } - - /** GIVEN error response then success WHEN retried THEN success is shown */ - @Test - fun retryingFromErrorStateAndSucceedingShowsTheData() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario( - ContentScenario.Error(false) - .then(ContentScenario.Success(false)) - ) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - homeRobot.swipeRefresh() - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - loopMainThreadFor(2000L) - - ContentData.contentSuccess.forEachIndexed { index, content -> - homeRobot.assertContainsItem(index, FavouriteContent(content, false)) - } - homeRobot.assertDidNotNavigateToAuth() - } - - /** GIVEN success then error WHEN retried THEN error is shown */ - @Test - fun errorIsShownIfTheDataIsFetchedAndErrorIsReceived() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario( - ContentScenario.Success(false) - .then(ContentScenario.Error(false)) - ) - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - homeRobot.swipeRefresh() - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - loopMainThreadUntilIdleWithIdlingResources() - mainDispatcherTestRule.advanceTimeBy(1000L) - loopMainThreadFor(1000) - - homeRobot - .assertContainsError() - .assertContainsNoItems() - .assertDidNotNavigateToAuth() - } - - /** GIVEN unauthenticated then success WHEN loaded THEN success is shown */ - @Test - fun authenticationIsHandledWithASingleLoading() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario( - ContentScenario.Unauthorized(false) - .then(ContentScenario.Success(true)) - ) - .setScenario(RefreshTokenScenario.Success) - - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - ContentData.contentSuccess.forEachIndexed { index, content -> - homeRobot.assertContainsItem(index, FavouriteContent(content, false)) - } - homeRobot.assertDidNotNavigateToAuth() - } - - /** GIVEN unauthenticated then error WHEN loaded THEN navigated to auth */ - @Test - fun sessionExpirationResultsInNavigation() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup - .setScenario(ContentScenario.Unauthorized(false)) - .setScenario(RefreshTokenScenario.Error) - - activityScenario = ActivityScenario.launch(HiltMainActivity::class.java) - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - - homeRobot.assertNavigatedToAuth() - } -} diff --git a/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt b/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt deleted file mode 100644 index b1ec4e2..0000000 --- a/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/login/AuthActivityTest.kt +++ /dev/null @@ -1,170 +0,0 @@ -package org.fnives.test.showcase.ui.login - -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import androidx.lifecycle.Lifecycle -import androidx.test.core.app.ActivityScenario -import androidx.test.ext.junit.runners.AndroidJUnit4 -import dagger.hilt.android.testing.HiltAndroidRule -import dagger.hilt.android.testing.HiltAndroidTest -import org.fnives.test.showcase.R -import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario -import org.fnives.test.showcase.testutils.MockServerScenarioSetupTestRule -import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory -import org.fnives.test.showcase.testutils.idling.Disposable -import org.fnives.test.showcase.testutils.idling.NetworkSynchronization -import org.fnives.test.showcase.testutils.robot.RobotTestRule -import org.fnives.test.showcase.ui.auth.HiltAuthActivity -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import javax.inject.Inject - -@Suppress("TestFunctionName") -@RunWith(AndroidJUnit4::class) -@HiltAndroidTest -class AuthActivityTest { - - private lateinit var activityScenario: ActivityScenario - - @Rule - @JvmField - val instantTaskExecutorRule = InstantTaskExecutorRule() - - @Rule - @JvmField - val snackbarVerificationTestRule = SpecificTestConfigurationsFactory.createSnackbarVerification() - - @Rule - @JvmField - val robotRule = RobotTestRule(LoginRobot()) - private val loginRobot get() = robotRule.robot - - @Rule - @JvmField - val mockServerScenarioSetupTestRule = MockServerScenarioSetupTestRule() - - @Rule - @JvmField - val mainDispatcherTestRule = SpecificTestConfigurationsFactory.createMainDispatcherTestRule() - - @Rule - @JvmField - val hiltRule = HiltAndroidRule(this) - - @Inject - lateinit var networkSynchronization: NetworkSynchronization - - private lateinit var disposable: Disposable - - @Before - fun setUp() { - SpecificTestConfigurationsFactory.createServerTypeConfiguration() - .invoke(mockServerScenarioSetupTestRule.mockServerScenarioSetup) - hiltRule.inject() - disposable = networkSynchronization.registerNetworkingSynchronization() - } - - @After - fun tearDown() { - activityScenario.moveToState(Lifecycle.State.DESTROYED) - disposable.dispose() - } - - /** GIVEN non empty password and username and successful response WHEN signIn THEN no error is shown and navigating to home */ - @Test - fun properLoginResultsInNavigationToHome() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup.setScenario( - AuthScenario.Success( - password = "alma", - username = "banan" - ) - ) - activityScenario = ActivityScenario.launch(HiltAuthActivity::class.java) - loginRobot - .setPassword("alma") - .setUsername("banan") - .assertPassword("alma") - .assertUsername("banan") - .clickOnLogin() - .assertLoadingBeforeRequests() - - mainDispatcherTestRule.advanceUntilIdleOrActivityIsDestroyed() - loginRobot.assertNavigatedToHome() - } - - /** GIVEN empty password and username WHEN signIn THEN error password is shown */ - @Test - fun emptyPasswordShowsProperErrorMessage() { - activityScenario = ActivityScenario.launch(HiltAuthActivity::class.java) - loginRobot - .setUsername("banan") - .assertUsername("banan") - .clickOnLogin() - .assertLoadingBeforeRequests() - - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - loginRobot.assertErrorIsShown(R.string.password_is_invalid) - .assertNotNavigatedToHome() - .assertNotLoading() - } - - /** GIVEN password and empty username WHEN signIn THEN error username is shown */ - @Test - fun emptyUserNameShowsProperErrorMessage() { - activityScenario = ActivityScenario.launch(HiltAuthActivity::class.java) - loginRobot - .setPassword("banan") - .assertPassword("banan") - .clickOnLogin() - .assertLoadingBeforeRequests() - - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - loginRobot.assertErrorIsShown(R.string.username_is_invalid) - .assertNotNavigatedToHome() - .assertNotLoading() - } - - /** GIVEN password and username and invalid credentials response WHEN signIn THEN error invalid credentials is shown */ - @Test - fun invalidCredentialsGivenShowsProperErrorMessage() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup.setScenario( - AuthScenario.InvalidCredentials(username = "alma", password = "banan") - ) - activityScenario = ActivityScenario.launch(HiltAuthActivity::class.java) - loginRobot - .setUsername("alma") - .setPassword("banan") - .assertUsername("alma") - .assertPassword("banan") - .clickOnLogin() - .assertLoadingBeforeRequests() - - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - loginRobot.assertErrorIsShown(R.string.credentials_invalid) - .assertNotNavigatedToHome() - .assertNotLoading() - } - - /** GIVEN password and username and error response WHEN signIn THEN error invalid credentials is shown */ - @Test - fun networkErrorShowsProperErrorMessage() { - mockServerScenarioSetupTestRule.mockServerScenarioSetup.setScenario( - AuthScenario.GenericError(username = "alma", password = "banan") - ) - activityScenario = ActivityScenario.launch(HiltAuthActivity::class.java) - loginRobot - .setUsername("alma") - .setPassword("banan") - .assertUsername("alma") - .assertPassword("banan") - .clickOnLogin() - .assertLoadingBeforeRequests() - - mainDispatcherTestRule.advanceUntilIdleWithIdlingResources() - loginRobot.assertErrorIsShown(R.string.something_went_wrong) - .assertNotNavigatedToHome() - .assertNotLoading() - } -} diff --git a/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt b/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt deleted file mode 100644 index f90d661..0000000 --- a/app/src/sharedTestHilt/java/org/fnives/test/showcase/ui/splash/SplashActivityTest.kt +++ /dev/null @@ -1,120 +0,0 @@ -package org.fnives.test.showcase.ui.splash - -import androidx.arch.core.executor.testing.InstantTaskExecutorRule -import androidx.lifecycle.Lifecycle -import androidx.test.core.app.ActivityScenario -import androidx.test.ext.junit.runners.AndroidJUnit4 -import dagger.hilt.android.testing.HiltAndroidRule -import dagger.hilt.android.testing.HiltAndroidTest -import org.fnives.test.showcase.testutils.MockServerScenarioSetupTestRule -import org.fnives.test.showcase.testutils.configuration.SpecificTestConfigurationsFactory -import org.fnives.test.showcase.testutils.idling.Disposable -import org.fnives.test.showcase.testutils.idling.NetworkSynchronization -import org.fnives.test.showcase.testutils.robot.RobotTestRule -import org.junit.After -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.junit.runner.RunWith -import org.koin.test.KoinTest -import javax.inject.Inject - -@Suppress("TestFunctionName") -@RunWith(AndroidJUnit4::class) -@HiltAndroidTest -class SplashActivityTest : KoinTest { - - private var activityScenario: ActivityScenario? = null - - private val splashRobot: SplashRobot get() = robotTestRule.robot - - @Rule - @JvmField - val instantTaskExecutorRule = InstantTaskExecutorRule() - - @Rule - @JvmField - val robotTestRule = RobotTestRule(SplashRobot()) - - @Rule - @JvmField - val mainDispatcherTestRule = SpecificTestConfigurationsFactory.createMainDispatcherTestRule() - - @Rule - @JvmField - val mockServerScenarioSetupTestRule = MockServerScenarioSetupTestRule() - - @Rule - @JvmField - val hiltRule = HiltAndroidRule(this) - - @Inject - lateinit var networkSynchronization: NetworkSynchronization - - var disposable: Disposable? = null - - @Before - fun setUp() { - SpecificTestConfigurationsFactory.createServerTypeConfiguration() - .invoke(mockServerScenarioSetupTestRule.mockServerScenarioSetup) - hiltRule.inject() - disposable = networkSynchronization.registerNetworkingSynchronization() - } - - @After - fun tearDown() { - activityScenario?.moveToState(Lifecycle.State.DESTROYED) - disposable?.dispose() - } - - /** GIVEN loggedInState WHEN opened THEN MainActivity is started */ - @Test - fun loggedInStateNavigatesToHome() { - splashRobot.setupLoggedInState(mainDispatcherTestRule, mockServerScenarioSetupTestRule.mockServerScenarioSetup) - - activityScenario = ActivityScenario.launch(HiltSplashActivity::class.java) - - mainDispatcherTestRule.advanceTimeBy(501) - - splashRobot.assertHomeIsStarted() - .assertAuthIsNotStarted() - } - - /** GIVEN loggedOffState WHEN opened THEN AuthActivity is started */ - @Test - fun loggedOutStatesNavigatesToAuthentication() { - splashRobot.setupLoggedOutState(mainDispatcherTestRule) - - activityScenario = ActivityScenario.launch(HiltSplashActivity::class.java) - - mainDispatcherTestRule.advanceTimeBy(501) - - splashRobot.assertAuthIsStarted() - .assertHomeIsNotStarted() - } - - @Test - fun loggedOutStatesNotEnoughTime() { - splashRobot.setupLoggedOutState(mainDispatcherTestRule) - - activityScenario = ActivityScenario.launch(HiltSplashActivity::class.java) - - mainDispatcherTestRule.advanceTimeBy(10) - - splashRobot.assertAuthIsNotStarted() - .assertHomeIsNotStarted() - } - - /** GIVEN loggedInState and not enough time WHEN opened THEN no activity is started */ - @Test - fun loggedInStatesNotEnoughTime() { - splashRobot.setupLoggedInState(mainDispatcherTestRule, mockServerScenarioSetupTestRule.mockServerScenarioSetup) - - activityScenario = ActivityScenario.launch(HiltSplashActivity::class.java) - - mainDispatcherTestRule.advanceTimeBy(10) - - splashRobot.assertHomeIsNotStarted() - .assertAuthIsNotStarted() - } -} diff --git a/app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/ActivityClassHolder.kt b/app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/ActivityClassHolder.kt deleted file mode 100644 index 357b766..0000000 --- a/app/src/sharedTestKoin/java/org/fnives/test/showcase/ui/ActivityClassHolder.kt +++ /dev/null @@ -1,14 +0,0 @@ -package org.fnives.test.showcase.ui - -import org.fnives.test.showcase.ui.auth.AuthActivity -import org.fnives.test.showcase.ui.home.MainActivity -import org.fnives.test.showcase.ui.splash.SplashActivity - -object ActivityClassHolder { - - fun authActivity() = AuthActivity::class - - fun mainActivity() = MainActivity::class - - fun splashActivity() = SplashActivity::class -} diff --git a/app/src/testKoin/java/org/fnives/test/showcase/di/DITest.kt b/app/src/test/java/org/fnives/test/showcase/di/DITest.kt similarity index 100% rename from app/src/testKoin/java/org/fnives/test/showcase/di/DITest.kt rename to app/src/test/java/org/fnives/test/showcase/di/DITest.kt diff --git a/build.gradle b/build.gradle index 77c70b4..d96f97a 100644 --- a/build.gradle +++ b/build.gradle @@ -2,14 +2,12 @@ buildscript { ext.kotlin_version = "1.6.10" ext.detekt_version = "1.19.0" - ext.hilt_version = "2.40.5" repositories { mavenCentral() google() maven { url "https://plugins.gradle.org/m2/" } } dependencies { - classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath 'com.android.tools.build:gradle:7.0.4' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jlleitschuh.gradle:ktlint-gradle:10.2.1" @@ -24,15 +22,6 @@ allprojects { repositories { mavenCentral() google() - maven { - url "https://maven.pkg.github.com/fknives/ReloadableHiltModule" - credentials { - username = project.findProperty("GITHUB_USERNAME") ?: System.getenv("GITHUB_USERNAME") - password = project.findProperty("GITHUB_TOKEN") ?: System.getenv("GITHUB_TOKEN") - } - // how to get token - // https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token - } } } @@ -40,17 +29,17 @@ task clean(type: Delete) { delete rootProject.buildDir } -task unitTests(dependsOn: ["app:testKoinDebugUnitTest", "app:testHiltDebugUnitTest", "core:test", "network:test"]){ +task unitTests(dependsOn: ["app:testDebugUnitTest", "core:test", "network:test"]){ group = 'Tests' description = 'Run all unit tests' } -task robolectricTests(dependsOn: ["app:testKoinDebugUnitTest", "app:testHiltDebugUnitTest"]){ +task robolectricTests(dependsOn: ["app:testDebugUnitTest"]){ group = 'Tests' description = 'Run all robolectric tests' } -task androidTests(dependsOn: ["app:connectedKoinDebugAndroidTest", "app:connectedHiltDebugAndroidTest"]){ +task androidTests(dependsOn: ["app:connectedDebugAndroidTest"]){ group = 'Tests' description = 'Run all Android tests' } diff --git a/core/build.gradle b/core/build.gradle index 33ca51c..fe8b936 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -25,18 +25,11 @@ dependencies { api project(":model") implementation project(":network") - // hilt - implementation "com.google.dagger:hilt-core:$hilt_version" - kapt "com.google.dagger:hilt-compiler:$hilt_version" - implementation "org.fnives.library.reloadable.module:annotation:$reloadable_module_version" - kapt "org.fnives.library.reloadable.module:annotation-processor:$reloadable_module_version" - testImplementation "io.insert-koin:koin-test-junit5:$koin_version" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" testImplementation "org.mockito.kotlin:mockito-kotlin:$testing_kotlin_mockito_version" testImplementation "org.junit.jupiter:junit-jupiter-engine:$testing_junit5_version" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$testing_junit5_version" - kaptTest "com.google.dagger:dagger-compiler:$hilt_version" testImplementation "com.squareup.retrofit2:retrofit:$retrofit_version" testImplementation "app.cash.turbine:turbine:$turbine_version" } \ No newline at end of file diff --git a/core/src/main/java/org/fnives/test/showcase/core/content/AddContentToFavouriteUseCase.kt b/core/src/main/java/org/fnives/test/showcase/core/content/AddContentToFavouriteUseCase.kt index 2483d1c..c5ea010 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/content/AddContentToFavouriteUseCase.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/content/AddContentToFavouriteUseCase.kt @@ -2,9 +2,8 @@ package org.fnives.test.showcase.core.content import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage import org.fnives.test.showcase.model.content.ContentId -import javax.inject.Inject -class AddContentToFavouriteUseCase @Inject internal constructor( +class AddContentToFavouriteUseCase internal constructor( private val favouriteContentLocalStorage: FavouriteContentLocalStorage ) { diff --git a/core/src/main/java/org/fnives/test/showcase/core/content/ContentRepository.kt b/core/src/main/java/org/fnives/test/showcase/core/content/ContentRepository.kt index 6b45ad3..56b9ec7 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/content/ContentRepository.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/content/ContentRepository.kt @@ -7,7 +7,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf -import org.fnives.test.showcase.core.di.hilt.LoggedInModuleInject import org.fnives.test.showcase.core.shared.Optional import org.fnives.test.showcase.core.shared.mapIntoResource import org.fnives.test.showcase.core.shared.wrapIntoAnswer @@ -15,7 +14,7 @@ import org.fnives.test.showcase.model.content.Content import org.fnives.test.showcase.model.shared.Resource import org.fnives.test.showcase.network.content.ContentRemoteSource -internal class ContentRepository @LoggedInModuleInject constructor( +internal class ContentRepository( private val contentRemoteSource: ContentRemoteSource ) { diff --git a/core/src/main/java/org/fnives/test/showcase/core/content/FetchContentUseCase.kt b/core/src/main/java/org/fnives/test/showcase/core/content/FetchContentUseCase.kt index 16944f5..90c7a5b 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/content/FetchContentUseCase.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/content/FetchContentUseCase.kt @@ -1,8 +1,6 @@ package org.fnives.test.showcase.core.content -import javax.inject.Inject - -class FetchContentUseCase @Inject internal constructor(private val contentRepository: ContentRepository) { +class FetchContentUseCase internal constructor(private val contentRepository: ContentRepository) { fun invoke() = contentRepository.fetch() } diff --git a/core/src/main/java/org/fnives/test/showcase/core/content/GetAllContentUseCase.kt b/core/src/main/java/org/fnives/test/showcase/core/content/GetAllContentUseCase.kt index 56b7c72..24a4b63 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/content/GetAllContentUseCase.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/content/GetAllContentUseCase.kt @@ -7,9 +7,8 @@ import org.fnives.test.showcase.model.content.Content import org.fnives.test.showcase.model.content.ContentId import org.fnives.test.showcase.model.content.FavouriteContent import org.fnives.test.showcase.model.shared.Resource -import javax.inject.Inject -class GetAllContentUseCase @Inject internal constructor( +class GetAllContentUseCase internal constructor( private val contentRepository: ContentRepository, private val favouriteContentLocalStorage: FavouriteContentLocalStorage ) { diff --git a/core/src/main/java/org/fnives/test/showcase/core/content/RemoveContentFromFavouritesUseCase.kt b/core/src/main/java/org/fnives/test/showcase/core/content/RemoveContentFromFavouritesUseCase.kt index 4c03f90..494af3e 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/content/RemoveContentFromFavouritesUseCase.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/content/RemoveContentFromFavouritesUseCase.kt @@ -2,9 +2,8 @@ package org.fnives.test.showcase.core.content import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage import org.fnives.test.showcase.model.content.ContentId -import javax.inject.Inject -class RemoveContentFromFavouritesUseCase @Inject internal constructor( +class RemoveContentFromFavouritesUseCase internal constructor( private val favouriteContentLocalStorage: FavouriteContentLocalStorage ) { diff --git a/core/src/main/java/org/fnives/test/showcase/core/di/koin/createCoreModule.kt b/core/src/main/java/org/fnives/test/showcase/core/di/createCoreModule.kt similarity index 95% rename from core/src/main/java/org/fnives/test/showcase/core/di/koin/createCoreModule.kt rename to core/src/main/java/org/fnives/test/showcase/core/di/createCoreModule.kt index 5f66810..721b26f 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/di/koin/createCoreModule.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/di/createCoreModule.kt @@ -14,7 +14,7 @@ import org.fnives.test.showcase.core.storage.NetworkSessionLocalStorageAdapter import org.fnives.test.showcase.core.storage.UserDataLocalStorage import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage import org.fnives.test.showcase.model.network.BaseUrl -import org.fnives.test.showcase.network.di.koin.createNetworkModules +import org.fnives.test.showcase.network.di.createNetworkModules import org.koin.core.module.Module import org.koin.core.scope.Scope import org.koin.dsl.module @@ -42,7 +42,7 @@ fun repositoryModule() = module { fun useCaseModule() = module { factory { LoginUseCase(get(), get()) } - factory { LogoutUseCase(get(), null) } + factory { LogoutUseCase(get()) } factory { GetAllContentUseCase(get(), get()) } factory { AddContentToFavouriteUseCase(get()) } factory { RemoveContentFromFavouritesUseCase(get()) } diff --git a/core/src/main/java/org/fnives/test/showcase/core/di/hilt/CoreModule.kt b/core/src/main/java/org/fnives/test/showcase/core/di/hilt/CoreModule.kt deleted file mode 100644 index 67887f9..0000000 --- a/core/src/main/java/org/fnives/test/showcase/core/di/hilt/CoreModule.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.fnives.test.showcase.core.di.hilt - -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import org.fnives.test.showcase.core.login.LogoutUseCase -import org.fnives.test.showcase.core.session.SessionExpirationAdapter -import org.fnives.test.showcase.core.storage.NetworkSessionLocalStorageAdapter -import org.fnives.test.showcase.core.storage.UserDataLocalStorage -import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener -import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage - -@InstallIn(SingletonComponent::class) -@Module -object CoreModule { - - @Provides - internal fun bindNetworkSessionLocalStorageAdapter( - networkSessionLocalStorageAdapter: NetworkSessionLocalStorageAdapter - ): NetworkSessionLocalStorage = networkSessionLocalStorageAdapter - - @Provides - internal fun bindNetworkSessionExpirationListener( - sessionExpirationAdapter: SessionExpirationAdapter - ): NetworkSessionExpirationListener = sessionExpirationAdapter - - @Provides - fun provideLogoutUseCase( - storage: UserDataLocalStorage, - reloadLoggedInModuleInjectModule: ReloadLoggedInModuleInjectModule - ): LogoutUseCase = LogoutUseCase(storage, reloadLoggedInModuleInjectModule) -} diff --git a/core/src/main/java/org/fnives/test/showcase/core/di/hilt/LoggedInModuleInject.kt b/core/src/main/java/org/fnives/test/showcase/core/di/hilt/LoggedInModuleInject.kt deleted file mode 100644 index 5032c97..0000000 --- a/core/src/main/java/org/fnives/test/showcase/core/di/hilt/LoggedInModuleInject.kt +++ /dev/null @@ -1,8 +0,0 @@ -package org.fnives.test.showcase.core.di.hilt - -import org.fnives.library.reloadable.module.annotation.ReloadableModule - -@ReloadableModule -@Target(AnnotationTarget.CONSTRUCTOR) -@Retention(AnnotationRetention.SOURCE) -annotation class LoggedInModuleInject diff --git a/core/src/main/java/org/fnives/test/showcase/core/login/IsUserLoggedInUseCase.kt b/core/src/main/java/org/fnives/test/showcase/core/login/IsUserLoggedInUseCase.kt index 1e21dd1..cb66a67 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/login/IsUserLoggedInUseCase.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/login/IsUserLoggedInUseCase.kt @@ -1,9 +1,8 @@ package org.fnives.test.showcase.core.login import org.fnives.test.showcase.core.storage.UserDataLocalStorage -import javax.inject.Inject -class IsUserLoggedInUseCase @Inject constructor( +class IsUserLoggedInUseCase( private val userDataLocalStorage: UserDataLocalStorage ) { diff --git a/core/src/main/java/org/fnives/test/showcase/core/login/LoginUseCase.kt b/core/src/main/java/org/fnives/test/showcase/core/login/LoginUseCase.kt index cf03c79..2a91780 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/login/LoginUseCase.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/login/LoginUseCase.kt @@ -7,9 +7,8 @@ import org.fnives.test.showcase.model.auth.LoginStatus import org.fnives.test.showcase.model.shared.Answer import org.fnives.test.showcase.network.auth.LoginRemoteSource import org.fnives.test.showcase.network.auth.model.LoginStatusResponses -import javax.inject.Inject -class LoginUseCase @Inject internal constructor( +class LoginUseCase internal constructor( private val loginRemoteSource: LoginRemoteSource, private val userDataLocalStorage: UserDataLocalStorage ) { diff --git a/core/src/main/java/org/fnives/test/showcase/core/login/LogoutUseCase.kt b/core/src/main/java/org/fnives/test/showcase/core/login/LogoutUseCase.kt index 15d6033..961a666 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/login/LogoutUseCase.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/login/LogoutUseCase.kt @@ -1,22 +1,15 @@ package org.fnives.test.showcase.core.login -import org.fnives.test.showcase.core.di.hilt.ReloadLoggedInModuleInjectModule import org.fnives.test.showcase.core.di.koin.repositoryModule import org.fnives.test.showcase.core.storage.UserDataLocalStorage import org.koin.core.context.loadKoinModules -import org.koin.mp.KoinPlatformTools class LogoutUseCase( - private val storage: UserDataLocalStorage, - private val reloadLoggedInModuleInjectModule: ReloadLoggedInModuleInjectModule? + private val storage: UserDataLocalStorage ) { suspend fun invoke() { - if (KoinPlatformTools.defaultContext().getOrNull() == null) { - reloadLoggedInModuleInjectModule?.reload() - } else { - loadKoinModules(repositoryModule()) - } + loadKoinModules(repositoryModule()) storage.session = null } } diff --git a/core/src/main/java/org/fnives/test/showcase/core/session/SessionExpirationAdapter.kt b/core/src/main/java/org/fnives/test/showcase/core/session/SessionExpirationAdapter.kt index 3571971..bc24d4a 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/session/SessionExpirationAdapter.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/session/SessionExpirationAdapter.kt @@ -1,9 +1,8 @@ package org.fnives.test.showcase.core.session import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener -import javax.inject.Inject -internal class SessionExpirationAdapter @Inject constructor( +internal class SessionExpirationAdapter( private val sessionExpirationListener: SessionExpirationListener ) : NetworkSessionExpirationListener { diff --git a/core/src/main/java/org/fnives/test/showcase/core/storage/NetworkSessionLocalStorageAdapter.kt b/core/src/main/java/org/fnives/test/showcase/core/storage/NetworkSessionLocalStorageAdapter.kt index 0d157f6..a9d5d77 100644 --- a/core/src/main/java/org/fnives/test/showcase/core/storage/NetworkSessionLocalStorageAdapter.kt +++ b/core/src/main/java/org/fnives/test/showcase/core/storage/NetworkSessionLocalStorageAdapter.kt @@ -2,9 +2,8 @@ package org.fnives.test.showcase.core.storage import org.fnives.test.showcase.model.session.Session import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage -import javax.inject.Inject -internal class NetworkSessionLocalStorageAdapter @Inject constructor( +internal class NetworkSessionLocalStorageAdapter( private val userDataLocalStorage: UserDataLocalStorage ) : NetworkSessionLocalStorage { diff --git a/core/src/test/java/org/fnives/test/showcase/core/login/koin/LogoutUseCaseTest.kt b/core/src/test/java/org/fnives/test/showcase/core/login/LogoutUseCaseTest.kt similarity index 93% rename from core/src/test/java/org/fnives/test/showcase/core/login/koin/LogoutUseCaseTest.kt rename to core/src/test/java/org/fnives/test/showcase/core/login/LogoutUseCaseTest.kt index 1c125e7..230ee1b 100644 --- a/core/src/test/java/org/fnives/test/showcase/core/login/koin/LogoutUseCaseTest.kt +++ b/core/src/test/java/org/fnives/test/showcase/core/login/LogoutUseCaseTest.kt @@ -1,10 +1,9 @@ -package org.fnives.test.showcase.core.login.koin +package org.fnives.test.showcase.core.login import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.fnives.test.showcase.core.content.ContentRepository import org.fnives.test.showcase.core.di.koin.createCoreModule -import org.fnives.test.showcase.core.login.LogoutUseCase import org.fnives.test.showcase.core.storage.UserDataLocalStorage import org.fnives.test.showcase.model.network.BaseUrl import org.junit.jupiter.api.AfterEach @@ -31,7 +30,7 @@ internal class LogoutUseCaseTest : KoinTest { @BeforeEach fun setUp() { mockUserDataLocalStorage = mock() - sut = LogoutUseCase(mockUserDataLocalStorage, null) + sut = LogoutUseCase(mockUserDataLocalStorage) startKoin { modules( createCoreModule( diff --git a/core/src/test/java/org/fnives/test/showcase/core/login/hilt/LogoutUseCaseTest.kt b/core/src/test/java/org/fnives/test/showcase/core/login/hilt/LogoutUseCaseTest.kt deleted file mode 100644 index a3fa397..0000000 --- a/core/src/test/java/org/fnives/test/showcase/core/login/hilt/LogoutUseCaseTest.kt +++ /dev/null @@ -1,62 +0,0 @@ -package org.fnives.test.showcase.core.login.hilt - -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.test.runTest -import org.fnives.test.showcase.core.content.ContentRepository -import org.fnives.test.showcase.core.login.LogoutUseCase -import org.fnives.test.showcase.core.storage.UserDataLocalStorage -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import org.mockito.kotlin.mock -import org.mockito.kotlin.times -import org.mockito.kotlin.verify -import org.mockito.kotlin.verifyNoMoreInteractions -import org.mockito.kotlin.verifyZeroInteractions -import javax.inject.Inject - -@Suppress("TestFunctionName") -@OptIn(ExperimentalCoroutinesApi::class) -internal class LogoutUseCaseTest { - - @Inject - lateinit var sut: LogoutUseCase - private lateinit var mockUserDataLocalStorage: UserDataLocalStorage - private lateinit var testCoreComponent: TestCoreComponent - - @Inject - lateinit var contentRepository: ContentRepository - - @BeforeEach - fun setUp() { - mockUserDataLocalStorage = mock() - testCoreComponent = DaggerTestCoreComponent.builder() - .setBaseUrl("https://a.b.com") - .setEnableLogging(true) - .setSessionExpirationListener(mock()) - .setUserDataLocalStorage(mockUserDataLocalStorage) - .build() - testCoreComponent.inject(this) - } - - @DisplayName("WHEN no call THEN storage is not interacted") - @Test - fun initializedDoesntAffectStorage() { - verifyZeroInteractions(mockUserDataLocalStorage) - } - - @DisplayName("WHEN logout invoked THEN storage is cleared") - @Test - fun logoutResultsInStorageCleaning() = runTest { - val repositoryBefore = contentRepository - - sut.invoke() - - testCoreComponent.inject(this@LogoutUseCaseTest) - val repositoryAfter = contentRepository - verify(mockUserDataLocalStorage, times(1)).session = null - verifyNoMoreInteractions(mockUserDataLocalStorage) - Assertions.assertNotSame(repositoryBefore, repositoryAfter) - } -} diff --git a/core/src/test/java/org/fnives/test/showcase/core/login/hilt/TestCoreComponent.kt b/core/src/test/java/org/fnives/test/showcase/core/login/hilt/TestCoreComponent.kt deleted file mode 100644 index f5d2997..0000000 --- a/core/src/test/java/org/fnives/test/showcase/core/login/hilt/TestCoreComponent.kt +++ /dev/null @@ -1,36 +0,0 @@ -package org.fnives.test.showcase.core.login.hilt - -import dagger.BindsInstance -import dagger.Component -import org.fnives.test.showcase.core.di.hilt.CoreModule -import org.fnives.test.showcase.core.di.hilt.ReloadLoggedInModuleInjectModuleImpl -import org.fnives.test.showcase.core.session.SessionExpirationListener -import org.fnives.test.showcase.core.storage.UserDataLocalStorage -import org.fnives.test.showcase.network.di.hilt.BindsBaseOkHttpClient -import org.fnives.test.showcase.network.di.hilt.HiltNetworkModule -import javax.inject.Singleton - -@Singleton -@Component(modules = [CoreModule::class, HiltNetworkModule::class, ReloadLoggedInModuleInjectModuleImpl::class, BindsBaseOkHttpClient::class]) -internal interface TestCoreComponent { - - @Component.Builder - interface Builder { - - @BindsInstance - fun setBaseUrl(baseUrl: String): Builder - - @BindsInstance - fun setEnableLogging(enableLogging: Boolean): Builder - - @BindsInstance - fun setSessionExpirationListener(listener: SessionExpirationListener): Builder - - @BindsInstance - fun setUserDataLocalStorage(storage: UserDataLocalStorage): Builder - - fun build(): TestCoreComponent - } - - fun inject(logoutUseCaseTest: LogoutUseCaseTest) -} diff --git a/gradlescripts/versions.gradle b/gradlescripts/versions.gradle index fecdcec..6ea8510 100644 --- a/gradlescripts/versions.gradle +++ b/gradlescripts/versions.gradle @@ -15,7 +15,6 @@ project.ext { retrofit_version = "2.9.0" okhttp_version = "4.9.1" moshi_version = "1.13.0" - reloadable_module_version = "0.1.0" testing_androidx_code_version = "1.4.0" testing_androidx_junit_version = "1.1.3" diff --git a/model/src/main/java/org/fnives/test/showcase/hilt/SessionLessQualifier.kt b/model/src/main/java/org/fnives/test/showcase/hilt/SessionLessQualifier.kt deleted file mode 100644 index 7760b2f..0000000 --- a/model/src/main/java/org/fnives/test/showcase/hilt/SessionLessQualifier.kt +++ /dev/null @@ -1,6 +0,0 @@ -package org.fnives.test.showcase.hilt - -import javax.inject.Qualifier - -@Qualifier -annotation class SessionLessQualifier diff --git a/model/src/main/java/org/fnives/test/showcase/hilt/SessionQualifier.kt b/model/src/main/java/org/fnives/test/showcase/hilt/SessionQualifier.kt deleted file mode 100644 index bba6af8..0000000 --- a/model/src/main/java/org/fnives/test/showcase/hilt/SessionQualifier.kt +++ /dev/null @@ -1,6 +0,0 @@ -package org.fnives.test.showcase.hilt - -import javax.inject.Qualifier - -@Qualifier -annotation class SessionQualifier diff --git a/network/build.gradle b/network/build.gradle index 0ac9855..cbd2de4 100644 --- a/network/build.gradle +++ b/network/build.gradle @@ -21,9 +21,6 @@ dependencies { // koin api "io.insert-koin:koin-core:$koin_version" - // hilt - implementation "com.google.dagger:hilt-core:$hilt_version" - api project(":model") testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version" @@ -33,6 +30,4 @@ dependencies { testImplementation "io.insert-koin:koin-test-junit5:$koin_version" testImplementation "org.skyscreamer:jsonassert:$testing_json_assert_version" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$testing_junit5_version" - kapt "com.google.dagger:hilt-compiler:$hilt_version" - kaptTest "com.google.dagger:dagger-compiler:$hilt_version" } \ No newline at end of file diff --git a/network/src/main/java/org/fnives/test/showcase/network/auth/LoginErrorConverter.kt b/network/src/main/java/org/fnives/test/showcase/network/auth/LoginErrorConverter.kt index 057064e..49a588b 100644 --- a/network/src/main/java/org/fnives/test/showcase/network/auth/LoginErrorConverter.kt +++ b/network/src/main/java/org/fnives/test/showcase/network/auth/LoginErrorConverter.kt @@ -7,9 +7,8 @@ import org.fnives.test.showcase.network.shared.ExceptionWrapper import org.fnives.test.showcase.network.shared.exceptions.ParsingException import retrofit2.HttpException import retrofit2.Response -import javax.inject.Inject -internal class LoginErrorConverter @Inject constructor() { +internal class LoginErrorConverter { @Throws(ParsingException::class) suspend fun invoke(request: suspend () -> Response): LoginStatusResponses = diff --git a/network/src/main/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceImpl.kt b/network/src/main/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceImpl.kt index 0a5bf85..5bb70af 100644 --- a/network/src/main/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceImpl.kt +++ b/network/src/main/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceImpl.kt @@ -7,9 +7,8 @@ import org.fnives.test.showcase.network.auth.model.LoginStatusResponses import org.fnives.test.showcase.network.shared.ExceptionWrapper import org.fnives.test.showcase.network.shared.exceptions.NetworkException import org.fnives.test.showcase.network.shared.exceptions.ParsingException -import javax.inject.Inject -internal class LoginRemoteSourceImpl @Inject constructor( +internal class LoginRemoteSourceImpl( private val loginService: LoginService, private val loginErrorConverter: LoginErrorConverter ) : LoginRemoteSource { diff --git a/network/src/main/java/org/fnives/test/showcase/network/content/ContentRemoteSourceImpl.kt b/network/src/main/java/org/fnives/test/showcase/network/content/ContentRemoteSourceImpl.kt index 25d830d..7748a46 100644 --- a/network/src/main/java/org/fnives/test/showcase/network/content/ContentRemoteSourceImpl.kt +++ b/network/src/main/java/org/fnives/test/showcase/network/content/ContentRemoteSourceImpl.kt @@ -4,9 +4,8 @@ import org.fnives.test.showcase.model.content.Content import org.fnives.test.showcase.model.content.ContentId import org.fnives.test.showcase.model.content.ImageUrl import org.fnives.test.showcase.network.shared.ExceptionWrapper -import javax.inject.Inject -internal class ContentRemoteSourceImpl @Inject constructor( +internal class ContentRemoteSourceImpl( private val contentService: ContentService ) : ContentRemoteSource { diff --git a/network/src/main/java/org/fnives/test/showcase/network/di/koin/createNetworkmodules.kt b/network/src/main/java/org/fnives/test/showcase/network/di/createNetworkmodules.kt similarity index 97% rename from network/src/main/java/org/fnives/test/showcase/network/di/koin/createNetworkmodules.kt rename to network/src/main/java/org/fnives/test/showcase/network/di/createNetworkmodules.kt index 2c84e77..b4b0e8b 100644 --- a/network/src/main/java/org/fnives/test/showcase/network/di/koin/createNetworkmodules.kt +++ b/network/src/main/java/org/fnives/test/showcase/network/di/createNetworkmodules.kt @@ -1,4 +1,4 @@ -package org.fnives.test.showcase.network.di.koin +package org.fnives.test.showcase.network.di import okhttp3.OkHttpClient import org.fnives.test.showcase.model.network.BaseUrl @@ -9,7 +9,6 @@ import org.fnives.test.showcase.network.auth.LoginService import org.fnives.test.showcase.network.content.ContentRemoteSource import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl import org.fnives.test.showcase.network.content.ContentService -import org.fnives.test.showcase.network.di.setupLogging import org.fnives.test.showcase.network.session.AuthenticationHeaderInterceptor import org.fnives.test.showcase.network.session.AuthenticationHeaderUtils import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener diff --git a/network/src/main/java/org/fnives/test/showcase/network/di/hilt/BindsBaseOkHttpClient.kt b/network/src/main/java/org/fnives/test/showcase/network/di/hilt/BindsBaseOkHttpClient.kt deleted file mode 100644 index 260f5ad..0000000 --- a/network/src/main/java/org/fnives/test/showcase/network/di/hilt/BindsBaseOkHttpClient.kt +++ /dev/null @@ -1,17 +0,0 @@ -package org.fnives.test.showcase.network.di.hilt - -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import okhttp3.OkHttpClient -import org.fnives.test.showcase.hilt.SessionLessQualifier - -@InstallIn(SingletonComponent::class) -@Module -abstract class BindsBaseOkHttpClient { - - @Binds - @SessionLessQualifier - abstract fun bindsSessionLess(okHttpClient: OkHttpClient): OkHttpClient -} diff --git a/network/src/main/java/org/fnives/test/showcase/network/di/hilt/HiltNetworkModule.kt b/network/src/main/java/org/fnives/test/showcase/network/di/hilt/HiltNetworkModule.kt deleted file mode 100644 index fe8d982..0000000 --- a/network/src/main/java/org/fnives/test/showcase/network/di/hilt/HiltNetworkModule.kt +++ /dev/null @@ -1,96 +0,0 @@ -package org.fnives.test.showcase.network.di.hilt - -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import okhttp3.OkHttpClient -import org.fnives.test.showcase.hilt.SessionLessQualifier -import org.fnives.test.showcase.hilt.SessionQualifier -import org.fnives.test.showcase.network.auth.LoginRemoteSource -import org.fnives.test.showcase.network.auth.LoginRemoteSourceImpl -import org.fnives.test.showcase.network.auth.LoginService -import org.fnives.test.showcase.network.content.ContentRemoteSource -import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl -import org.fnives.test.showcase.network.content.ContentService -import org.fnives.test.showcase.network.di.setupLogging -import org.fnives.test.showcase.network.session.AuthenticationHeaderInterceptor -import org.fnives.test.showcase.network.session.AuthenticationHeaderUtils -import org.fnives.test.showcase.network.session.SessionAuthenticator -import org.fnives.test.showcase.network.shared.PlatformInterceptor -import retrofit2.Converter -import retrofit2.Retrofit -import retrofit2.converter.moshi.MoshiConverterFactory -import javax.inject.Singleton - -@InstallIn(SingletonComponent::class) -@Module -object HiltNetworkModule { - - @Provides - @Singleton - fun provideConverterFactory(): Converter.Factory = MoshiConverterFactory.create() - - @Provides - @Singleton - fun provideSessionLessOkHttpClient(enableLogging: Boolean) = - OkHttpClient.Builder() - .addInterceptor(PlatformInterceptor()) - .setupLogging(enableLogging) - .build() - - @Provides - @Singleton - @SessionLessQualifier - fun provideSessionLessRetrofit( - baseUrl: String, - converterFactory: Converter.Factory, - @SessionLessQualifier okHttpClient: OkHttpClient - ) = Retrofit.Builder() - .baseUrl(baseUrl) - .addConverterFactory(converterFactory) - .client(okHttpClient) - .build() - - @Provides - @Singleton - @SessionQualifier - internal fun provideSessionOkHttpClient( - @SessionLessQualifier okHttpClient: OkHttpClient, - sessionAuthenticator: SessionAuthenticator, - authenticationHeaderUtils: AuthenticationHeaderUtils - ) = - okHttpClient - .newBuilder() - .authenticator(sessionAuthenticator) - .addInterceptor(AuthenticationHeaderInterceptor(authenticationHeaderUtils)) - .build() - - @Provides - @Singleton - @SessionQualifier - fun provideSessionRetrofit( - @SessionLessQualifier retrofit: Retrofit, - @SessionQualifier okHttpClient: OkHttpClient - ) = retrofit.newBuilder() - .client(okHttpClient) - .build() - - @Provides - internal fun bindContentRemoteSource( - contentRemoteSourceImpl: ContentRemoteSourceImpl - ): ContentRemoteSource = contentRemoteSourceImpl - - @Provides - internal fun bindLoginRemoteSource( - loginRemoteSource: LoginRemoteSourceImpl - ): LoginRemoteSource = loginRemoteSource - - @Provides - internal fun provideLoginService(@SessionLessQualifier retrofit: Retrofit): LoginService = - retrofit.create(LoginService::class.java) - - @Provides - internal fun provideContentService(@SessionQualifier retrofit: Retrofit): ContentService = - retrofit.create(ContentService::class.java) -} diff --git a/network/src/main/java/org/fnives/test/showcase/network/session/AuthenticationHeaderUtils.kt b/network/src/main/java/org/fnives/test/showcase/network/session/AuthenticationHeaderUtils.kt index 56601b1..c734c42 100644 --- a/network/src/main/java/org/fnives/test/showcase/network/session/AuthenticationHeaderUtils.kt +++ b/network/src/main/java/org/fnives/test/showcase/network/session/AuthenticationHeaderUtils.kt @@ -1,9 +1,8 @@ package org.fnives.test.showcase.network.session import okhttp3.Request -import javax.inject.Inject -internal class AuthenticationHeaderUtils @Inject constructor( +internal class AuthenticationHeaderUtils( private val networkSessionLocalStorage: NetworkSessionLocalStorage ) { diff --git a/network/src/main/java/org/fnives/test/showcase/network/session/SessionAuthenticator.kt b/network/src/main/java/org/fnives/test/showcase/network/session/SessionAuthenticator.kt index 544574c..df1c411 100644 --- a/network/src/main/java/org/fnives/test/showcase/network/session/SessionAuthenticator.kt +++ b/network/src/main/java/org/fnives/test/showcase/network/session/SessionAuthenticator.kt @@ -6,9 +6,8 @@ import okhttp3.Request import okhttp3.Response import okhttp3.Route import org.fnives.test.showcase.network.auth.LoginRemoteSourceImpl -import javax.inject.Inject -internal class SessionAuthenticator @Inject constructor( +internal class SessionAuthenticator( private val networkSessionLocalStorage: NetworkSessionLocalStorage, private val loginRemoteSource: LoginRemoteSourceImpl, private val authenticationHeaderUtils: AuthenticationHeaderUtils, diff --git a/network/src/test/java/org/fnives/test/showcase/network/TestNetworkComponent.kt b/network/src/test/java/org/fnives/test/showcase/network/TestNetworkComponent.kt deleted file mode 100644 index 9300e01..0000000 --- a/network/src/test/java/org/fnives/test/showcase/network/TestNetworkComponent.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.fnives.test.showcase.network - -import dagger.BindsInstance -import dagger.Component -import org.fnives.test.showcase.network.auth.hilt.LoginRemoteSourceRefreshActionImplTest -import org.fnives.test.showcase.network.auth.hilt.LoginRemoteSourceTest -import org.fnives.test.showcase.network.content.hilt.ContentRemoteSourceImplTest -import org.fnives.test.showcase.network.content.hilt.SessionExpirationTest -import org.fnives.test.showcase.network.di.hilt.BindsBaseOkHttpClient -import org.fnives.test.showcase.network.di.hilt.HiltNetworkModule -import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener -import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage -import javax.inject.Singleton - -@Singleton -@Component(modules = [HiltNetworkModule::class, BindsBaseOkHttpClient::class]) -interface TestNetworkComponent { - - @Component.Builder - interface Builder { - - @BindsInstance - fun setBaseUrl(baseUrl: String): Builder - - @BindsInstance - fun setEnableLogging(enableLogging: Boolean): Builder - - @BindsInstance - fun setNetworkSessionLocalStorage(storage: NetworkSessionLocalStorage): Builder - - @BindsInstance - fun setNetworkSessionExpirationListener(listener: NetworkSessionExpirationListener): Builder - - fun build(): TestNetworkComponent - } - - fun inject(contentRemoteSourceImplTest: ContentRemoteSourceImplTest) - - fun inject(sessionExpirationTest: SessionExpirationTest) - - fun inject(loginRemoteSourceRefreshActionImplTest: LoginRemoteSourceRefreshActionImplTest) - - fun inject(loginRemoteSourceTest: LoginRemoteSourceTest) -} diff --git a/network/src/test/java/org/fnives/test/showcase/network/auth/koin/LoginRemoteSourceRefreshActionImplTest.kt b/network/src/test/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceRefreshActionImplTest.kt similarity index 96% rename from network/src/test/java/org/fnives/test/showcase/network/auth/koin/LoginRemoteSourceRefreshActionImplTest.kt rename to network/src/test/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceRefreshActionImplTest.kt index 1709388..90f7cf5 100644 --- a/network/src/test/java/org/fnives/test/showcase/network/auth/koin/LoginRemoteSourceRefreshActionImplTest.kt +++ b/network/src/test/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceRefreshActionImplTest.kt @@ -1,9 +1,8 @@ -package org.fnives.test.showcase.network.auth.koin +package org.fnives.test.showcase.network.auth import kotlinx.coroutines.runBlocking import org.fnives.test.showcase.model.network.BaseUrl -import org.fnives.test.showcase.network.auth.LoginRemoteSourceImpl -import org.fnives.test.showcase.network.di.koin.createNetworkModules +import org.fnives.test.showcase.network.di.createNetworkModules import org.fnives.test.showcase.network.mockserver.ContentData import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage diff --git a/network/src/test/java/org/fnives/test/showcase/network/auth/koin/LoginRemoteSourceTest.kt b/network/src/test/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceTest.kt similarity index 96% rename from network/src/test/java/org/fnives/test/showcase/network/auth/koin/LoginRemoteSourceTest.kt rename to network/src/test/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceTest.kt index 56ce6d3..6e08ee1 100644 --- a/network/src/test/java/org/fnives/test/showcase/network/auth/koin/LoginRemoteSourceTest.kt +++ b/network/src/test/java/org/fnives/test/showcase/network/auth/LoginRemoteSourceTest.kt @@ -1,11 +1,10 @@ -package org.fnives.test.showcase.network.auth.koin +package org.fnives.test.showcase.network.auth import kotlinx.coroutines.runBlocking import org.fnives.test.showcase.model.auth.LoginCredentials import org.fnives.test.showcase.model.network.BaseUrl -import org.fnives.test.showcase.network.auth.LoginRemoteSource import org.fnives.test.showcase.network.auth.model.LoginStatusResponses -import org.fnives.test.showcase.network.di.koin.createNetworkModules +import org.fnives.test.showcase.network.di.createNetworkModules import org.fnives.test.showcase.network.mockserver.ContentData import org.fnives.test.showcase.network.mockserver.ContentData.createExpectedLoginRequestJson import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario diff --git a/network/src/test/java/org/fnives/test/showcase/network/auth/hilt/LoginRemoteSourceRefreshActionImplTest.kt b/network/src/test/java/org/fnives/test/showcase/network/auth/hilt/LoginRemoteSourceRefreshActionImplTest.kt deleted file mode 100644 index 87705a0..0000000 --- a/network/src/test/java/org/fnives/test/showcase/network/auth/hilt/LoginRemoteSourceRefreshActionImplTest.kt +++ /dev/null @@ -1,103 +0,0 @@ -package org.fnives.test.showcase.network.auth.hilt - -import kotlinx.coroutines.runBlocking -import org.fnives.test.showcase.network.DaggerTestNetworkComponent -import org.fnives.test.showcase.network.auth.LoginRemoteSourceImpl -import org.fnives.test.showcase.network.mockserver.ContentData -import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario -import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage -import org.fnives.test.showcase.network.shared.MockServerScenarioSetupExtensions -import org.fnives.test.showcase.network.shared.exceptions.NetworkException -import org.fnives.test.showcase.network.shared.exceptions.ParsingException -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.RegisterExtension -import org.mockito.kotlin.mock -import javax.inject.Inject - -@Suppress("TestFunctionName") -class LoginRemoteSourceRefreshActionImplTest { - - @Inject - internal lateinit var sut: LoginRemoteSourceImpl - private lateinit var mockNetworkSessionLocalStorage: NetworkSessionLocalStorage - - @RegisterExtension - @JvmField - val mockServerScenarioSetupExtensions = MockServerScenarioSetupExtensions() - private val mockServerScenarioSetup - get() = mockServerScenarioSetupExtensions.mockServerScenarioSetup - - @BeforeEach - fun setUp() { - mockNetworkSessionLocalStorage = mock() - DaggerTestNetworkComponent.builder() - .setBaseUrl(mockServerScenarioSetupExtensions.url) - .setEnableLogging(true) - .setNetworkSessionLocalStorage(mockNetworkSessionLocalStorage) - .setNetworkSessionExpirationListener(mock()) - .build() - .inject(this) - } - - @DisplayName("GIVEN successful response WHEN refresh request is fired THEN session is returned") - @Test - fun successResponseResultsInSession() = runBlocking { - mockServerScenarioSetup.setScenario(RefreshTokenScenario.Success) - val expected = ContentData.refreshSuccessResponse - - val actual = sut.refresh(ContentData.refreshSuccessResponse.refreshToken) - - Assertions.assertEquals(expected, actual) - } - - @DisplayName("GIVEN successful response WHEN refresh request is fired THEN the request is setup properly") - @Test - fun refreshRequestIsSetupProperly() = runBlocking { - mockServerScenarioSetup.setScenario(RefreshTokenScenario.Success, false) - - sut.refresh(ContentData.refreshSuccessResponse.refreshToken) - val request = mockServerScenarioSetup.takeRequest() - - Assertions.assertEquals("PUT", request.method) - Assertions.assertEquals("Android", request.getHeader("Platform")) - Assertions.assertEquals(null, request.getHeader("Authorization")) - Assertions.assertEquals( - "/login/${ContentData.refreshSuccessResponse.refreshToken}", - request.path - ) - Assertions.assertEquals("", request.body.readUtf8()) - } - - @DisplayName("GIVEN internal error response WHEN refresh request is fired THEN network exception is thrown") - @Test - fun generalErrorResponseResultsInNetworkException() { - mockServerScenarioSetup.setScenario(RefreshTokenScenario.Error) - - Assertions.assertThrows(NetworkException::class.java) { - runBlocking { sut.refresh(ContentData.refreshSuccessResponse.refreshToken) } - } - } - - @DisplayName("GIVEN invalid json response WHEN refresh request is fired THEN network exception is thrown") - @Test - fun jsonErrorResponseResultsInParsingException() { - mockServerScenarioSetup.setScenario(RefreshTokenScenario.UnexpectedJsonAsSuccessResponse) - - Assertions.assertThrows(ParsingException::class.java) { - runBlocking { sut.refresh(ContentData.loginSuccessResponse.refreshToken) } - } - } - - @DisplayName("GIVEN malformed json response WHEN refresh request is fired THEN parsing exception is thrown") - @Test - fun malformedJsonErrorResponseResultsInParsingException() { - mockServerScenarioSetup.setScenario(RefreshTokenScenario.MalformedJson) - - Assertions.assertThrows(ParsingException::class.java) { - runBlocking { sut.refresh(ContentData.loginSuccessResponse.refreshToken) } - } - } -} diff --git a/network/src/test/java/org/fnives/test/showcase/network/auth/hilt/LoginRemoteSourceTest.kt b/network/src/test/java/org/fnives/test/showcase/network/auth/hilt/LoginRemoteSourceTest.kt deleted file mode 100644 index 3e49a32..0000000 --- a/network/src/test/java/org/fnives/test/showcase/network/auth/hilt/LoginRemoteSourceTest.kt +++ /dev/null @@ -1,120 +0,0 @@ -package org.fnives.test.showcase.network.auth.hilt - -import kotlinx.coroutines.runBlocking -import org.fnives.test.showcase.model.auth.LoginCredentials -import org.fnives.test.showcase.network.DaggerTestNetworkComponent -import org.fnives.test.showcase.network.auth.LoginRemoteSource -import org.fnives.test.showcase.network.auth.model.LoginStatusResponses -import org.fnives.test.showcase.network.mockserver.ContentData -import org.fnives.test.showcase.network.mockserver.ContentData.createExpectedLoginRequestJson -import org.fnives.test.showcase.network.mockserver.scenario.auth.AuthScenario -import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage -import org.fnives.test.showcase.network.shared.MockServerScenarioSetupExtensions -import org.fnives.test.showcase.network.shared.exceptions.NetworkException -import org.fnives.test.showcase.network.shared.exceptions.ParsingException -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.RegisterExtension -import org.mockito.kotlin.mock -import org.skyscreamer.jsonassert.JSONAssert -import org.skyscreamer.jsonassert.JSONCompareMode -import javax.inject.Inject - -@Suppress("TestFunctionName") -class LoginRemoteSourceTest { - - @Inject - internal lateinit var sut: LoginRemoteSource - - @RegisterExtension - @JvmField - val mockServerScenarioSetupExtensions = MockServerScenarioSetupExtensions() - private val mockServerScenarioSetup - get() = mockServerScenarioSetupExtensions.mockServerScenarioSetup - - @BeforeEach - fun setUp() { - val mockNetworkSessionLocalStorage = mock() - DaggerTestNetworkComponent.builder() - .setBaseUrl(mockServerScenarioSetupExtensions.url) - .setEnableLogging(true) - .setNetworkSessionLocalStorage(mockNetworkSessionLocalStorage) - .setNetworkSessionExpirationListener(mock()) - .build() - .inject(this) - } - - @DisplayName("GIVEN successful response WHEN request is fired THEN login status success is returned") - @Test - fun successResponseIsParsedProperly() = runBlocking { - mockServerScenarioSetup.setScenario(AuthScenario.Success("a", "b")) - val expected = LoginStatusResponses.Success(ContentData.loginSuccessResponse) - - val actual = sut.login(LoginCredentials("a", "b")) - - Assertions.assertEquals(expected, actual) - } - - @DisplayName("GIVEN successful response WHEN request is fired THEN the request is setup properly") - @Test - fun requestProperlySetup() = runBlocking { - mockServerScenarioSetup.setScenario(AuthScenario.Success("a", "b"), false) - - sut.login(LoginCredentials("a", "b")) - val request = mockServerScenarioSetup.takeRequest() - - Assertions.assertEquals("POST", request.method) - Assertions.assertEquals("Android", request.getHeader("Platform")) - Assertions.assertEquals(null, request.getHeader("Authorization")) - Assertions.assertEquals("/login", request.path) - val loginRequest = createExpectedLoginRequestJson("a", "b") - JSONAssert.assertEquals( - loginRequest, - request.body.readUtf8(), - JSONCompareMode.NON_EXTENSIBLE - ) - } - - @DisplayName("GIVEN bad request response WHEN request is fired THEN login status invalid credentials is returned") - @Test - fun badRequestMeansInvalidCredentials() = runBlocking { - mockServerScenarioSetup.setScenario(AuthScenario.InvalidCredentials("a", "b")) - val expected = LoginStatusResponses.InvalidCredentials - - val actual = sut.login(LoginCredentials("a", "b")) - - Assertions.assertEquals(expected, actual) - } - - @DisplayName("GIVEN internal error response WHEN request is fired THEN network exception is thrown") - @Test - fun genericErrorMeansNetworkError() { - mockServerScenarioSetup.setScenario(AuthScenario.GenericError("a", "b")) - - Assertions.assertThrows(NetworkException::class.java) { - runBlocking { sut.login(LoginCredentials("a", "b")) } - } - } - - @DisplayName("GIVEN invalid json response WHEN request is fired THEN network exception is thrown") - @Test - fun invalidJsonMeansParsingException() { - mockServerScenarioSetup.setScenario(AuthScenario.UnexpectedJsonAsSuccessResponse("a", "b")) - - Assertions.assertThrows(ParsingException::class.java) { - runBlocking { sut.login(LoginCredentials("a", "b")) } - } - } - - @DisplayName("GIVEN malformed json response WHEN request is fired THEN network exception is thrown") - @Test - fun malformedJsonMeansParsingException() { - mockServerScenarioSetup.setScenario(AuthScenario.MalformedJsonAsSuccessResponse("a", "b")) - - Assertions.assertThrows(ParsingException::class.java) { - runBlocking { sut.login(LoginCredentials("a", "b")) } - } - } -} diff --git a/network/src/test/java/org/fnives/test/showcase/network/content/CodeKataSessionExpirationTest.kt b/network/src/test/java/org/fnives/test/showcase/network/content/CodeKataSessionExpirationTest.kt index 0a68a41..3b694b2 100644 --- a/network/src/test/java/org/fnives/test/showcase/network/content/CodeKataSessionExpirationTest.kt +++ b/network/src/test/java/org/fnives/test/showcase/network/content/CodeKataSessionExpirationTest.kt @@ -3,7 +3,7 @@ package org.fnives.test.showcase.network.content import kotlinx.coroutines.runBlocking import okhttp3.mockwebserver.MockWebServer import org.fnives.test.showcase.model.network.BaseUrl -import org.fnives.test.showcase.network.di.koin.createNetworkModules +import org.fnives.test.showcase.network.di.createNetworkModules import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage import org.junit.jupiter.api.AfterEach diff --git a/network/src/test/java/org/fnives/test/showcase/network/content/koin/ContentRemoteSourceImplTest.kt b/network/src/test/java/org/fnives/test/showcase/network/content/ContentRemoteSourceImplTest.kt similarity index 96% rename from network/src/test/java/org/fnives/test/showcase/network/content/koin/ContentRemoteSourceImplTest.kt rename to network/src/test/java/org/fnives/test/showcase/network/content/ContentRemoteSourceImplTest.kt index 400aba6..352488f 100644 --- a/network/src/test/java/org/fnives/test/showcase/network/content/koin/ContentRemoteSourceImplTest.kt +++ b/network/src/test/java/org/fnives/test/showcase/network/content/ContentRemoteSourceImplTest.kt @@ -1,9 +1,8 @@ -package org.fnives.test.showcase.network.content.koin +package org.fnives.test.showcase.network.content import kotlinx.coroutines.runBlocking import org.fnives.test.showcase.model.network.BaseUrl -import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl -import org.fnives.test.showcase.network.di.koin.createNetworkModules +import org.fnives.test.showcase.network.di.createNetworkModules import org.fnives.test.showcase.network.mockserver.ContentData import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage diff --git a/network/src/test/java/org/fnives/test/showcase/network/content/koin/SessionExpirationTest.kt b/network/src/test/java/org/fnives/test/showcase/network/content/SessionExpirationTest.kt similarity index 96% rename from network/src/test/java/org/fnives/test/showcase/network/content/koin/SessionExpirationTest.kt rename to network/src/test/java/org/fnives/test/showcase/network/content/SessionExpirationTest.kt index a3fc945..f521175 100644 --- a/network/src/test/java/org/fnives/test/showcase/network/content/koin/SessionExpirationTest.kt +++ b/network/src/test/java/org/fnives/test/showcase/network/content/SessionExpirationTest.kt @@ -1,10 +1,9 @@ -package org.fnives.test.showcase.network.content.koin +package org.fnives.test.showcase.network.content import kotlinx.coroutines.runBlocking import org.fnives.test.showcase.model.network.BaseUrl import org.fnives.test.showcase.model.session.Session -import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl -import org.fnives.test.showcase.network.di.koin.createNetworkModules +import org.fnives.test.showcase.network.di.createNetworkModules import org.fnives.test.showcase.network.mockserver.ContentData import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario diff --git a/network/src/test/java/org/fnives/test/showcase/network/content/hilt/ContentRemoteSourceImplTest.kt b/network/src/test/java/org/fnives/test/showcase/network/content/hilt/ContentRemoteSourceImplTest.kt deleted file mode 100644 index 0b4c0c0..0000000 --- a/network/src/test/java/org/fnives/test/showcase/network/content/hilt/ContentRemoteSourceImplTest.kt +++ /dev/null @@ -1,121 +0,0 @@ -package org.fnives.test.showcase.network.content.hilt - -import kotlinx.coroutines.runBlocking -import org.fnives.test.showcase.network.DaggerTestNetworkComponent -import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl -import org.fnives.test.showcase.network.mockserver.ContentData -import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario -import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage -import org.fnives.test.showcase.network.shared.MockServerScenarioSetupExtensions -import org.fnives.test.showcase.network.shared.exceptions.NetworkException -import org.fnives.test.showcase.network.shared.exceptions.ParsingException -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.RegisterExtension -import org.koin.test.inject -import org.mockito.kotlin.doReturn -import org.mockito.kotlin.mock -import org.mockito.kotlin.whenever -import javax.inject.Inject - -@Suppress("TestFunctionName") -class ContentRemoteSourceImplTest { - - @Inject - internal lateinit var sut: ContentRemoteSourceImpl - - @RegisterExtension - @JvmField - val mockServerScenarioSetupExtensions = MockServerScenarioSetupExtensions() - private lateinit var mockNetworkSessionLocalStorage: NetworkSessionLocalStorage - private val mockServerScenarioSetup - get() = mockServerScenarioSetupExtensions.mockServerScenarioSetup - - @BeforeEach - fun setUp() { - mockNetworkSessionLocalStorage = mock() - DaggerTestNetworkComponent.builder() - .setBaseUrl(mockServerScenarioSetupExtensions.url) - .setEnableLogging(true) - .setNetworkSessionLocalStorage(mockNetworkSessionLocalStorage) - .setNetworkSessionExpirationListener(mock()) - .build() - .inject(this) - } - - @DisplayName("GIVEN successful response WHEN getting content THEN its parsed and returned correctly") - @Test - fun successResponseParsing() = runBlocking { - whenever(mockNetworkSessionLocalStorage.session).doReturn(ContentData.loginSuccessResponse) - mockServerScenarioSetup.setScenario(ContentScenario.Success(false)) - val expected = ContentData.contentSuccess - - val actual = sut.get() - - Assertions.assertEquals(expected, actual) - } - - @DisplayName("GIVEN successful response WHEN getting content THEN the request is setup properly") - @Test - fun successResponseRequestIsCorrect() = runBlocking { - whenever(mockNetworkSessionLocalStorage.session).doReturn(ContentData.loginSuccessResponse) - mockServerScenarioSetup.setScenario(ContentScenario.Success(false), false) - - sut.get() - val request = mockServerScenarioSetup.takeRequest() - - Assertions.assertEquals("GET", request.method) - Assertions.assertEquals("Android", request.getHeader("Platform")) - Assertions.assertEquals(ContentData.loginSuccessResponse.accessToken, request.getHeader("Authorization")) - Assertions.assertEquals("/content", request.path) - Assertions.assertEquals("", request.body.readUtf8()) - } - - @DisplayName("GIVEN response with missing Field WHEN getting content THEN invalid is ignored others are returned") - @Test - fun dataMissingFieldIsIgnored() = runBlocking { - whenever(mockNetworkSessionLocalStorage.session).doReturn(ContentData.loginSuccessResponse) - mockServerScenarioSetup.setScenario(ContentScenario.SuccessWithMissingFields(false)) - - val expected = ContentData.contentSuccessWithMissingFields - - val actual = sut.get() - - Assertions.assertEquals(expected, actual) - } - - @DisplayName("GIVEN error response WHEN getting content THEN network request is thrown") - @Test - fun errorResponseResultsInNetworkException() { - whenever(mockNetworkSessionLocalStorage.session).doReturn(ContentData.loginSuccessResponse) - mockServerScenarioSetup.setScenario(ContentScenario.Error(false)) - - Assertions.assertThrows(NetworkException::class.java) { - runBlocking { sut.get() } - } - } - - @DisplayName("GIVEN unexpected json response WHEN getting content THEN parsing request is thrown") - @Test - fun unexpectedJSONResultsInParsingException() { - whenever(mockNetworkSessionLocalStorage.session).doReturn(ContentData.loginSuccessResponse) - mockServerScenarioSetup.setScenario(ContentScenario.UnexpectedJsonAsSuccessResponse(false)) - - Assertions.assertThrows(ParsingException::class.java) { - runBlocking { sut.get() } - } - } - - @DisplayName("GIVEN malformed json response WHEN getting content THEN parsing request is thrown") - @Test - fun malformedJSONResultsInParsingException() { - whenever(mockNetworkSessionLocalStorage.session).doReturn(ContentData.loginSuccessResponse) - mockServerScenarioSetup.setScenario(ContentScenario.MalformedJsonAsSuccessResponse(false)) - - Assertions.assertThrows(ParsingException::class.java) { - runBlocking { sut.get() } - } - } -} diff --git a/network/src/test/java/org/fnives/test/showcase/network/content/hilt/SessionExpirationTest.kt b/network/src/test/java/org/fnives/test/showcase/network/content/hilt/SessionExpirationTest.kt deleted file mode 100644 index f684fee..0000000 --- a/network/src/test/java/org/fnives/test/showcase/network/content/hilt/SessionExpirationTest.kt +++ /dev/null @@ -1,110 +0,0 @@ -package org.fnives.test.showcase.network.content.hilt - -import kotlinx.coroutines.runBlocking -import org.fnives.test.showcase.model.session.Session -import org.fnives.test.showcase.network.DaggerTestNetworkComponent -import org.fnives.test.showcase.network.content.ContentRemoteSourceImpl -import org.fnives.test.showcase.network.mockserver.ContentData -import org.fnives.test.showcase.network.mockserver.scenario.content.ContentScenario -import org.fnives.test.showcase.network.mockserver.scenario.refresh.RefreshTokenScenario -import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener -import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage -import org.fnives.test.showcase.network.shared.MockServerScenarioSetupExtensions -import org.fnives.test.showcase.network.shared.exceptions.NetworkException -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.DisplayName -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.RegisterExtension -import org.koin.test.inject -import org.mockito.kotlin.anyOrNull -import org.mockito.kotlin.doAnswer -import org.mockito.kotlin.doReturn -import org.mockito.kotlin.mock -import org.mockito.kotlin.times -import org.mockito.kotlin.verify -import org.mockito.kotlin.verifyNoMoreInteractions -import org.mockito.kotlin.verifyZeroInteractions -import org.mockito.kotlin.whenever -import javax.inject.Inject - -@Suppress("TestFunctionName") -class SessionExpirationTest { - - @Inject - internal lateinit var sut: ContentRemoteSourceImpl - - @RegisterExtension - @JvmField - val mockServerScenarioSetupExtensions = MockServerScenarioSetupExtensions() - private val mockServerScenarioSetup - get() = mockServerScenarioSetupExtensions.mockServerScenarioSetup - private lateinit var mockNetworkSessionLocalStorage: NetworkSessionLocalStorage - private lateinit var mockNetworkSessionExpirationListener: NetworkSessionExpirationListener - - @BeforeEach - fun setUp() { - mockNetworkSessionLocalStorage = mock() - mockNetworkSessionExpirationListener = mock() - DaggerTestNetworkComponent.builder() - .setBaseUrl(mockServerScenarioSetupExtensions.url) - .setEnableLogging(true) - .setNetworkSessionLocalStorage(mockNetworkSessionLocalStorage) - .setNetworkSessionExpirationListener(mockNetworkSessionExpirationListener) - .build() - .inject(this) - } - - @DisplayName("GIVEN 401 THEN refresh token ok response WHEN content requested THE tokens are refreshed and request retried with new tokens") - @Test - fun successRefreshResultsInRequestRetry() = runBlocking { - var sessionToReturnByMock: Session? = ContentData.loginSuccessResponse - mockServerScenarioSetup.setScenario( - ContentScenario.Unauthorized(false) - .then(ContentScenario.Success(true)), - false - ) - mockServerScenarioSetup.setScenario(RefreshTokenScenario.Success, false) - whenever(mockNetworkSessionLocalStorage.session).doAnswer { sessionToReturnByMock } - doAnswer { sessionToReturnByMock = it.arguments[0] as Session? } - .whenever(mockNetworkSessionLocalStorage).session = anyOrNull() - - sut.get() - - mockServerScenarioSetup.takeRequest() - val refreshRequest = mockServerScenarioSetup.takeRequest() - val retryAfterTokenRefreshRequest = mockServerScenarioSetup.takeRequest() - - Assertions.assertEquals("PUT", refreshRequest.method) - Assertions.assertEquals( - "/login/${ContentData.loginSuccessResponse.refreshToken}", - refreshRequest.path - ) - Assertions.assertEquals(null, refreshRequest.getHeader("Authorization")) - Assertions.assertEquals("Android", refreshRequest.getHeader("Platform")) - Assertions.assertEquals("", refreshRequest.body.readUtf8()) - Assertions.assertEquals( - ContentData.refreshSuccessResponse.accessToken, - retryAfterTokenRefreshRequest.getHeader("Authorization") - ) - verify(mockNetworkSessionLocalStorage, times(1)).session = - ContentData.refreshSuccessResponse - verifyZeroInteractions(mockNetworkSessionExpirationListener) - } - - @DisplayName("GIVEN 401 THEN failing refresh WHEN content requested THE error is returned and callback is Called") - @Test - fun failingRefreshResultsInSessionExpiration() = runBlocking { - whenever(mockNetworkSessionLocalStorage.session).doReturn(ContentData.loginSuccessResponse) - mockServerScenarioSetup.setScenario(ContentScenario.Unauthorized(false)) - mockServerScenarioSetup.setScenario(RefreshTokenScenario.Error) - - Assertions.assertThrows(NetworkException::class.java) { - runBlocking { sut.get() } - } - verify(mockNetworkSessionLocalStorage, times(3)).session - verify(mockNetworkSessionLocalStorage, times(1)).session = null - verifyNoMoreInteractions(mockNetworkSessionLocalStorage) - verify(mockNetworkSessionExpirationListener, times(1)).onSessionExpired() - } -} From bc19355a7075b1fab887067104e6341bd8fec692 Mon Sep 17 00:00:00 2001 From: Gergely Hegedus Date: Mon, 24 Jan 2022 17:53:34 +0200 Subject: [PATCH 2/2] Issue#31 Fix codeAnalysis errors --- core/build.gradle | 6 ------ gradlescripts/testoptions.gradle | 7 +++++++ .../test/showcase/network/auth/LoginErrorConverterTest.kt | 8 +++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/core/build.gradle b/core/build.gradle index fe8b936..e2b19e3 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -9,12 +9,6 @@ java { targetCompatibility = JavaVersion.VERSION_1_8 } -compileKotlin { - kotlinOptions { - freeCompilerArgs += ['-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi'] - } -} - kapt { correctErrorTypes = true } diff --git a/gradlescripts/testoptions.gradle b/gradlescripts/testoptions.gradle index c7b068b..42b9166 100644 --- a/gradlescripts/testoptions.gradle +++ b/gradlescripts/testoptions.gradle @@ -8,6 +8,13 @@ subprojects { module -> showStandardStreams true } } + module.tasks.configureEach { task -> + if (task.taskIdentity.type.toString() == "class org.jetbrains.kotlin.gradle.tasks.KotlinCompile") { + task.kotlinOptions { + freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" + } + } + } } plugins.withId("com.android.application") { diff --git a/network/src/test/java/org/fnives/test/showcase/network/auth/LoginErrorConverterTest.kt b/network/src/test/java/org/fnives/test/showcase/network/auth/LoginErrorConverterTest.kt index d066313..4357ad8 100644 --- a/network/src/test/java/org/fnives/test/showcase/network/auth/LoginErrorConverterTest.kt +++ b/network/src/test/java/org/fnives/test/showcase/network/auth/LoginErrorConverterTest.kt @@ -1,8 +1,9 @@ package org.fnives.test.showcase.network.auth import com.squareup.moshi.JsonDataException +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.test.runTest import okhttp3.internal.http.RealResponseBody import okio.Buffer import org.fnives.test.showcase.model.session.Session @@ -18,6 +19,7 @@ import retrofit2.Response import java.io.IOException @Suppress("TestFunctionName") +@OptIn(ExperimentalCoroutinesApi::class) class LoginErrorConverterTest { private lateinit var sut: LoginErrorConverter @@ -49,7 +51,7 @@ class LoginErrorConverterTest { @DisplayName("GIVEN 400 error response WHEN parsing login error THEN invalid credentials is returned") @Test - fun code400ResponseResultsInInvalidCredentials() = runBlockingTest { + fun code400ResponseResultsInInvalidCredentials() = runTest { val expected = LoginStatusResponses.InvalidCredentials val actual = sut.invoke { @@ -62,7 +64,7 @@ class LoginErrorConverterTest { @DisplayName("GIVEN successful response WHEN parsing login error THEN successful response is returned") @Test - fun successResponseResultsInSessionResponse() = runBlockingTest { + fun successResponseResultsInSessionResponse() = runTest { val loginResponse = LoginResponse("a", "r") val expectedSession = Session(accessToken = loginResponse.accessToken, refreshToken = loginResponse.refreshToken) val expected = LoginStatusResponses.Success(expectedSession)