diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7085961cb..be82874dd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -12,7 +12,6 @@ plugins { android { compileSdk = Libs.Project.compileSdkVersion - buildToolsVersion = Libs.Project.buildToolsVersion defaultConfig { applicationId = Libs.Project.applicationId @@ -21,7 +20,7 @@ android { versionCode = Libs.Project.versionCode versionName = Libs.Project.versionName - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + testInstrumentationRunner = "com.ivy.wallet.HiltTestRunner" kapt { arguments { @@ -206,4 +205,12 @@ dependencies { //THIS IS NOT RIGHT: Implementation for IdlingResource access on both Debug & Release //Without having this dependency "lintRelease" fails implementation(Libs.Testing.Compose.junit4) + //-------------------------------------- + + //Hilt Testing setup + androidTestImplementation(Libs.Testing.Hilt.daggerHilt) + kaptAndroidTest(Libs.Testing.Hilt.kaptHilt) + implementation(Libs.Testing.Hilt.androidTestRunner) + implementation(Libs.Testing.Hilt.androidWork) + //------------------------------------------------------------------- } diff --git a/app/src/androidTest/java/com/ivy/wallet/HiltTestRunner.kt b/app/src/androidTest/java/com/ivy/wallet/HiltTestRunner.kt new file mode 100644 index 000000000..d00ad1665 --- /dev/null +++ b/app/src/androidTest/java/com/ivy/wallet/HiltTestRunner.kt @@ -0,0 +1,14 @@ +package com.ivy.wallet + +import android.app.Application +import android.content.Context +import androidx.test.runner.AndroidJUnitRunner +import dagger.hilt.android.testing.HiltTestApplication + +// A custom runner to set up the instrumented application class for tests. +class HiltTestRunner : AndroidJUnitRunner() { + + override fun newApplication(cl: ClassLoader?, name: String?, context: Context?): Application { + return super.newApplication(cl, HiltTestApplication::class.java.name, context) + } +} \ No newline at end of file diff --git a/app/src/androidTest/java/com/ivy/wallet/compose/BasicOperationsTest.kt b/app/src/androidTest/java/com/ivy/wallet/compose/BasicOperationsTest.kt index d038af670..9d80314c6 100644 --- a/app/src/androidTest/java/com/ivy/wallet/compose/BasicOperationsTest.kt +++ b/app/src/androidTest/java/com/ivy/wallet/compose/BasicOperationsTest.kt @@ -5,15 +5,18 @@ import androidx.compose.ui.test.hasText import androidx.compose.ui.test.performClick import com.ivy.wallet.compose.helpers.AmountInput import com.ivy.wallet.compose.helpers.OnboardingFlow -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.runBlocking +import dagger.hilt.android.testing.HiltAndroidTest import org.junit.Test +@HiltAndroidTest class BasicOperationsTest : IvyComposeTest() { - @ExperimentalCoroutinesApi @Test - fun OnboardAndAdjustBalance() = runBlocking { + fun contextLoads() { + } + + @Test + fun OnboardAndAdjustBalance() { val onboarding = OnboardingFlow(composeTestRule) val amountInput = AmountInput(composeTestRule) @@ -34,6 +37,8 @@ class BasicOperationsTest : IvyComposeTest() { .performClick() amountInput.pressNumber(1) + + composeTestRule.printTree() // amountInput.pressNumber(0) // amountInput.pressNumber(2) // amountInput.pressNumber(5) diff --git a/app/src/androidTest/java/com/ivy/wallet/compose/IvyComposeTest.kt b/app/src/androidTest/java/com/ivy/wallet/compose/IvyComposeTest.kt index 50e7e563e..59634b64f 100644 --- a/app/src/androidTest/java/com/ivy/wallet/compose/IvyComposeTest.kt +++ b/app/src/androidTest/java/com/ivy/wallet/compose/IvyComposeTest.kt @@ -1,21 +1,30 @@ package com.ivy.wallet.compose import android.content.Context +import android.util.Log import androidx.compose.ui.test.IdlingResource import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.test.platform.app.InstrumentationRegistry +import androidx.work.Configuration +import androidx.work.impl.utils.SynchronousExecutor +import androidx.work.testing.WorkManagerTestInitHelper import com.ivy.wallet.base.TestIdlingResource import com.ivy.wallet.base.TestingContext import com.ivy.wallet.persistence.IvyRoomDatabase import com.ivy.wallet.persistence.SharedPrefs import com.ivy.wallet.ui.IvyActivity +import com.ivy.wallet.ui.IvyContext +import dagger.hilt.android.testing.HiltAndroidRule +import dagger.hilt.android.testing.HiltAndroidTest import org.junit.After import org.junit.Before import org.junit.Rule +import javax.inject.Inject +@HiltAndroidTest abstract class IvyComposeTest { - //TODO: Setup Hilt, too - //https://developer.android.com/training/dependency-injection/hilt-testing + @get:Rule + var hiltRule = HiltAndroidRule(this) @get:Rule val composeTestRule = createAndroidComposeRule() @@ -23,11 +32,25 @@ abstract class IvyComposeTest { private var idlingResource: IdlingResource? = null + @Inject + lateinit var ivyContext: IvyContext + @Before fun setUp() { + TestIdlingResource.reset() idlingResource = TestIdlingResource.idlingResource composeTestRule.registerIdlingResource(idlingResource!!) + + val config = Configuration.Builder() + .setMinimumLoggingLevel(Log.DEBUG) + .setExecutor(SynchronousExecutor()) + .build() + WorkManagerTestInitHelper.initializeTestWorkManager(context(), config) + hiltRule.inject() + TestingContext.inTest = true + + resetApp() } @After @@ -37,23 +60,29 @@ abstract class IvyComposeTest { } TestingContext.inTest = false + resetApp() } - protected fun resetApp() { + private fun resetApp() { clearSharedPrefs() deleteDatabase() + resetIvyContext() + } + + private fun clearSharedPrefs() { + SharedPrefs(context()).removeAll() } - protected fun clearSharedPrefs() { - SharedPrefs(targetContext()).removeAll() + private fun deleteDatabase() { + IvyRoomDatabase.create(context()).reset() } - protected fun deleteDatabase() { - targetContext().deleteDatabase(IvyRoomDatabase.DB_NAME) + private fun resetIvyContext() { + ivyContext.reset() } - private fun targetContext(): Context { + private fun context(): Context { return InstrumentationRegistry.getInstrumentation().targetContext } diff --git a/app/src/androidTest/java/com/ivy/wallet/compose/OnboardingTest.kt b/app/src/androidTest/java/com/ivy/wallet/compose/OnboardingTest.kt index 463214d4b..9fa3e0984 100644 --- a/app/src/androidTest/java/com/ivy/wallet/compose/OnboardingTest.kt +++ b/app/src/androidTest/java/com/ivy/wallet/compose/OnboardingTest.kt @@ -4,10 +4,16 @@ import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.hasText import com.ivy.wallet.compose.helpers.MainBottomBar import com.ivy.wallet.compose.helpers.OnboardingFlow +import dagger.hilt.android.testing.HiltAndroidTest import org.junit.Test +@HiltAndroidTest class OnboardingTest : IvyComposeTest() { + @Test + fun contextLoads() { + } + @Test fun OnboardingShortestPath() { val onboarding = OnboardingFlow(composeTestRule) @@ -24,6 +30,4 @@ class OnboardingTest : IvyComposeTest() { composeTestRule.onNode(hasText("Cash")) .assertIsDisplayed() } - - } \ No newline at end of file diff --git a/app/src/main/java/com/ivy/wallet/base/ComposeTesting.kt b/app/src/main/java/com/ivy/wallet/base/ComposeTesting.kt index e374aa51c..d53430b14 100644 --- a/app/src/main/java/com/ivy/wallet/base/ComposeTesting.kt +++ b/app/src/main/java/com/ivy/wallet/base/ComposeTesting.kt @@ -30,4 +30,8 @@ object TestIdlingResource { throw IllegalStateException("TestIdlingResource counter is corrupted! value = ${counter.get()}") } } + + fun reset() { + counter.set(0) + } } \ No newline at end of file diff --git a/app/src/main/java/com/ivy/wallet/di/AppModule.kt b/app/src/main/java/com/ivy/wallet/di/AppModule.kt index f96f3969f..a8b2202fd 100644 --- a/app/src/main/java/com/ivy/wallet/di/AppModule.kt +++ b/app/src/main/java/com/ivy/wallet/di/AppModule.kt @@ -91,7 +91,6 @@ object AppModule { ): IvyRoomDatabase { return IvyRoomDatabase.create( applicationContext = appContext, - gson = Gson() ) } diff --git a/app/src/main/java/com/ivy/wallet/persistence/IvyRoomDatabase.kt b/app/src/main/java/com/ivy/wallet/persistence/IvyRoomDatabase.kt index a6e95fa0d..6f00ad9b6 100644 --- a/app/src/main/java/com/ivy/wallet/persistence/IvyRoomDatabase.kt +++ b/app/src/main/java/com/ivy/wallet/persistence/IvyRoomDatabase.kt @@ -5,7 +5,6 @@ import androidx.room.Database import androidx.room.Room import androidx.room.RoomDatabase import androidx.room.TypeConverters -import com.google.gson.Gson import com.ivy.wallet.model.entity.* import com.ivy.wallet.persistence.dao.* import com.ivy.wallet.persistence.migration.* @@ -43,8 +42,7 @@ abstract class IvyRoomDatabase : RoomDatabase() { companion object { const val DB_NAME = "ivywallet.db" - fun create(applicationContext: Context, gson: Gson): IvyRoomDatabase { - RoomTypeConverters.gson = gson + fun create(applicationContext: Context): IvyRoomDatabase { return Room .databaseBuilder( applicationContext, diff --git a/app/src/main/java/com/ivy/wallet/persistence/RoomTypeConverters.kt b/app/src/main/java/com/ivy/wallet/persistence/RoomTypeConverters.kt index a634b71f4..4b4ba6475 100644 --- a/app/src/main/java/com/ivy/wallet/persistence/RoomTypeConverters.kt +++ b/app/src/main/java/com/ivy/wallet/persistence/RoomTypeConverters.kt @@ -1,7 +1,6 @@ package com.ivy.wallet.persistence import androidx.room.TypeConverter -import com.google.gson.Gson import com.ivy.wallet.base.epochMilliToDateTime import com.ivy.wallet.base.toEpochMilli import com.ivy.wallet.model.AuthProviderType @@ -13,11 +12,6 @@ import java.util.* @SuppressWarnings("unused") class RoomTypeConverters { - - companion object { - lateinit var gson: Gson - } - @TypeConverter fun saveDate(localDateTime: LocalDateTime?): Long? = localDateTime?.toEpochMilli() diff --git a/app/src/main/java/com/ivy/wallet/ui/IvyContext.kt b/app/src/main/java/com/ivy/wallet/ui/IvyContext.kt index 99a7bf638..254862147 100644 --- a/app/src/main/java/com/ivy/wallet/ui/IvyContext.kt +++ b/app/src/main/java/com/ivy/wallet/ui/IvyContext.kt @@ -215,4 +215,14 @@ class IvyContext { fun switchTheme(theme: Theme) { this.theme = theme } + + //Testing -------------------------------------------------------------------------------------- + fun reset() { + mainTab = MainTab.HOME + startDayOfMonth = 1 + currentScreen = null + isPremium = false + transactionsListState = null + resetBackStack() + } } diff --git a/buildSrc/src/main/java/com/ivy/wallet/buildsrc/dependencies.kt b/buildSrc/src/main/java/com/ivy/wallet/buildsrc/dependencies.kt index 99dd63c90..a13fda2e2 100644 --- a/buildSrc/src/main/java/com/ivy/wallet/buildsrc/dependencies.kt +++ b/buildSrc/src/main/java/com/ivy/wallet/buildsrc/dependencies.kt @@ -25,8 +25,7 @@ object Libs { const val versionCode = 86 //Compile SDK & Build Tools - const val compileSdkVersion = 30 - const val buildToolsVersion = "30.0.3" + const val compileSdkVersion = 31 //App const val applicationId = "com.ivy.wallet" @@ -52,7 +51,7 @@ object Libs { const val coreKtx = "androidx.core:core-ktx:1.5.0" //URL: https://developer.android.com/jetpack/androidx/releases/work - internal const val workVersion = "2.6.0-beta01" + internal const val workVersion = "2.7.1" const val workRuntime = "androidx.work:work-runtime-ktx:$workVersion" const val biometrics = "androidx.biometric:biometric:1.1.0" @@ -215,5 +214,14 @@ object Libs { const val composeTestRule = "androidx.compose.ui:ui-test-manifest:${AndroidX.Compose.version}" } + + object Hilt { + //https://developer.android.com/training/dependency-injection/hilt-testing + + val daggerHilt = "com.google.dagger:hilt-android-testing:${Libs.Hilt.version}" + val kaptHilt = "com.google.dagger:hilt-android-compiler:${Libs.Hilt.version}" + val androidTestRunner = "androidx.test:runner:1.4.0" + val androidWork = "androidx.work:work-testing:${Libs.AndroidX.workVersion}" + } } } \ No newline at end of file