diff --git a/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/ArtemisApplication.kt b/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/ArtemisApplication.kt index 022cccecc..0207d0daf 100644 --- a/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/ArtemisApplication.kt +++ b/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/ArtemisApplication.kt @@ -9,24 +9,8 @@ import coil3.ImageLoader import coil3.PlatformContext import coil3.SingletonImageLoader import coil3.memory.MemoryCache -import de.tum.informatics.www1.artemis.native_app.android.db.dbModule import de.tum.informatics.www1.artemis.native_app.core.common.ArtemisNotificationChannel import de.tum.informatics.www1.artemis.native_app.core.common.CurrentActivityListener -import de.tum.informatics.www1.artemis.native_app.core.data.dataModule -import de.tum.informatics.www1.artemis.native_app.core.datastore.datastoreModule -import de.tum.informatics.www1.artemis.native_app.core.device.deviceModule -import de.tum.informatics.www1.artemis.native_app.core.ui.uiModule -import de.tum.informatics.www1.artemis.native_app.core.websocket.websocketModule -import de.tum.informatics.www1.artemis.native_app.feature.courseregistration.courseRegistrationModule -import de.tum.informatics.www1.artemis.native_app.feature.courseview.courseViewModule -import de.tum.informatics.www1.artemis.native_app.feature.dashboard.dashboardModule -import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.exerciseModule -import de.tum.informatics.www1.artemis.native_app.feature.lectureview.lectureModule -import de.tum.informatics.www1.artemis.native_app.feature.login.loginModule -import de.tum.informatics.www1.artemis.native_app.feature.metis.communicationModule -import de.tum.informatics.www1.artemis.native_app.feature.push.pushModule -import de.tum.informatics.www1.artemis.native_app.feature.quiz.quizParticipationModule -import de.tum.informatics.www1.artemis.native_app.feature.settings.settingsModule import io.sentry.Sentry import kotlinx.coroutines.flow.MutableStateFlow import org.koin.android.ext.koin.androidContext @@ -49,24 +33,7 @@ class ArtemisApplication : Application(), SingletonImageLoader.Factory, CurrentA androidContext(this@ArtemisApplication) workManagerFactory() - modules( - dataModule, - uiModule, - datastoreModule, - deviceModule, - websocketModule, - courseRegistrationModule, - courseViewModule, - dashboardModule, - loginModule, - exerciseModule, - communicationModule, - quizParticipationModule, - settingsModule, - lectureModule, - pushModule, - dbModule - ) + modules(appModule) } ArtemisNotificationChannel.entries.forEach { notificationChannel -> diff --git a/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/app_module.kt b/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/app_module.kt new file mode 100644 index 000000000..c2817f1ee --- /dev/null +++ b/app/src/main/java/de/tum/informatics/www1/artemis/native_app/android/app_module.kt @@ -0,0 +1,38 @@ +package de.tum.informatics.www1.artemis.native_app.android + +import de.tum.informatics.www1.artemis.native_app.android.db.dbModule +import de.tum.informatics.www1.artemis.native_app.core.data.dataModule +import de.tum.informatics.www1.artemis.native_app.core.datastore.datastoreModule +import de.tum.informatics.www1.artemis.native_app.core.device.deviceModule +import de.tum.informatics.www1.artemis.native_app.core.ui.uiModule +import de.tum.informatics.www1.artemis.native_app.core.websocket.websocketModule +import de.tum.informatics.www1.artemis.native_app.feature.courseregistration.courseRegistrationModule +import de.tum.informatics.www1.artemis.native_app.feature.courseview.courseViewModule +import de.tum.informatics.www1.artemis.native_app.feature.dashboard.dashboardModule +import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.exerciseModule +import de.tum.informatics.www1.artemis.native_app.feature.lectureview.lectureModule +import de.tum.informatics.www1.artemis.native_app.feature.login.loginModule +import de.tum.informatics.www1.artemis.native_app.feature.metis.communicationModule +import de.tum.informatics.www1.artemis.native_app.feature.push.pushModule +import de.tum.informatics.www1.artemis.native_app.feature.quiz.quizParticipationModule +import de.tum.informatics.www1.artemis.native_app.feature.settings.settingsModule +import org.koin.dsl.module + +val appModule = module { includes( + dataModule, + uiModule, + datastoreModule, + deviceModule, + websocketModule, + courseRegistrationModule, + courseViewModule, + dashboardModule, + loginModule, + exerciseModule, + communicationModule, + quizParticipationModule, + settingsModule, + lectureModule, + pushModule, + dbModule +)} \ No newline at end of file diff --git a/feature/core-modules-test/build.gradle.kts b/feature/core-modules-test/build.gradle.kts index 83aaf84d4..47682367c 100644 --- a/feature/core-modules-test/build.gradle.kts +++ b/feature/core-modules-test/build.gradle.kts @@ -14,9 +14,12 @@ dependencies { implementation(libs.kotlinx.datetime) + testImplementation(project(":app")) + testImplementation(project(":core:core-test")) testImplementation(project(":feature:login")) testImplementation(project(":feature:login-test")) - testImplementation(project(":core:core-test")) + testImplementation(project(":feature:metis:shared")) + testImplementation(project(":feature:quiz")) kover(project(":core:data")) } diff --git a/feature/core-modules-test/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/coremodulestest/AppModuleTest.kt b/feature/core-modules-test/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/coremodulestest/AppModuleTest.kt new file mode 100644 index 000000000..783091552 --- /dev/null +++ b/feature/core-modules-test/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/coremodulestest/AppModuleTest.kt @@ -0,0 +1,45 @@ +package de.tum.informatics.www1.artemis.native_app.feature.coremodulestest + +import android.app.Application +import android.content.Context +import androidx.lifecycle.SavedStateHandle +import androidx.work.WorkerParameters +import de.tum.informatics.www1.artemis.native_app.android.appModule +import de.tum.informatics.www1.artemis.native_app.core.common.CurrentActivityListener +import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest +import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.StandalonePostId +import de.tum.informatics.www1.artemis.native_app.feature.quiz.QuizType +import org.junit.Test +import org.junit.experimental.categories.Category +import org.junit.runner.RunWith +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.test.verify.verify +import org.robolectric.RobolectricTestRunner +import kotlin.coroutines.CoroutineContext + +@OptIn(KoinExperimentalAPI::class) +@Category(UnitTest::class) +@RunWith(RobolectricTestRunner::class) +class AppModuleTest { + + @Test + fun checkKoinModule() { + + // Verify Koin configuration + appModule.verify( + extraTypes = listOf( + CoroutineContext::class, + SavedStateHandle::class, + Boolean::class, + Long::class, + StandalonePostId::class, + Application::class, + CurrentActivityListener::class, + Context::class, + WorkerParameters::class, + QuizType.WorkableQuizType::class, + QuizType.ViewableQuizType::class, + ) + ) + } +} \ No newline at end of file diff --git a/feature/course-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/BaseCourseTest.kt b/feature/course-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/BaseCourseTest.kt index 31c810471..811d06145 100644 --- a/feature/course-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/BaseCourseTest.kt +++ b/feature/course-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/BaseCourseTest.kt @@ -1,7 +1,6 @@ package de.tum.informatics.www1.artemis.native_app.feature.courseview import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.test.platform.app.InstrumentationRegistry import de.tum.informatics.www1.artemis.native_app.core.model.Course @@ -20,10 +19,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.login.test.testLoginMo import org.junit.Before import org.junit.Rule import org.koin.android.ext.koin.androidContext -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi -import org.koin.mp.KoinPlatformTools import org.koin.test.KoinTestRule import org.koin.test.get @@ -47,7 +42,6 @@ abstract class BaseCourseTest : BaseComposeTest() { } } - @OptIn(KoinInternalApi::class) internal fun setupAndDisplayCourseUi(): CourseViewModel { val viewModel = CourseViewModel( courseId = course.id!!, @@ -61,27 +55,21 @@ abstract class BaseCourseTest : BaseComposeTest() { ) composeTestRule.setContent { - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - CourseUiScreen( - modifier = Modifier.fillMaxSize(), - viewModel = viewModel, - courseId = course.id!!, - conversationId = DEFAULT_CONVERSATION_ID, - postId = DEFAULT_POST_ID, - username = "", - onNavigateToExercise = {}, - onNavigateToExerciseResultView = {}, - onNavigateToTextExerciseParticipation = { _, _ -> }, - onParticipateInQuiz = { _, _ -> }, - onClickViewQuizResults = { _, _ -> }, - onNavigateToLecture = {}, - onNavigateBack = {} - ) - } + CourseUiScreen( + modifier = Modifier.fillMaxSize(), + viewModel = viewModel, + courseId = course.id!!, + conversationId = DEFAULT_CONVERSATION_ID, + postId = DEFAULT_POST_ID, + username = "", + onNavigateToExercise = {}, + onNavigateToExerciseResultView = {}, + onNavigateToTextExerciseParticipation = { _, _ -> }, + onParticipateInQuiz = { _, _ -> }, + onClickViewQuizResults = { _, _ -> }, + onNavigateToLecture = {}, + onNavigateBack = {} + ) } return viewModel diff --git a/feature/exercise-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exerciseview/exercise_view_module.kt b/feature/exercise-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exerciseview/exercise_module.kt similarity index 100% rename from feature/exercise-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exerciseview/exercise_view_module.kt rename to feature/exercise-view/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exerciseview/exercise_module.kt diff --git a/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/exercise_moduleTest.kt b/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/exercise_moduleTest.kt new file mode 100644 index 000000000..719b18223 --- /dev/null +++ b/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/exercise_moduleTest.kt @@ -0,0 +1,45 @@ +package de.tum.informatics.www1.artemis.native_app.feature.exercise_view + +import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.CourseExerciseService +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.ExerciseService +import de.tum.informatics.www1.artemis.native_app.core.datastore.AccountService +import de.tum.informatics.www1.artemis.native_app.core.datastore.ServerConfigurationService +import de.tum.informatics.www1.artemis.native_app.core.device.NetworkStatusProvider +import de.tum.informatics.www1.artemis.native_app.core.websocket.LiveParticipationService +import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.ExerciseViewModel +import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.exerciseModule +import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.participate.textexercise.TextExerciseParticipationViewModel +import org.junit.Test +import org.junit.experimental.categories.Category +import org.junit.runner.RunWith +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.test.verify.definition +import org.koin.test.verify.verify +import org.robolectric.RobolectricTestRunner +import kotlin.coroutines.CoroutineContext + +@RunWith(RobolectricTestRunner::class) +@Category(UnitTest::class) +internal class exercise_moduleTest { + + @OptIn(KoinExperimentalAPI::class) + @Test + fun checkKoinModule() { + exerciseModule.verify( + injections = listOf( + definition(Long::class), + definition(Long::class, Long::class) + ), + extraTypes = listOf( + ServerConfigurationService::class, + NetworkStatusProvider::class, + AccountService::class, + CoroutineContext::class, + ExerciseService::class, + LiveParticipationService::class, + CourseExerciseService::class + ) + ) + } +} \ No newline at end of file diff --git a/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/ExerciseOverviewE2eTest.kt b/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/ExerciseOverviewE2eTest.kt index 8b395d1cb..762a55fa8 100644 --- a/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/ExerciseOverviewE2eTest.kt +++ b/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/ExerciseOverviewE2eTest.kt @@ -1,7 +1,6 @@ package de.tum.informatics.www1.artemis.native_app.feature.exercise_view.participate.text_exercise import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.hasText @@ -18,10 +17,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.home.Exer import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi -import org.koin.mp.KoinPlatformTools import org.koin.test.get import org.robolectric.RobolectricTestRunner import de.tum.informatics.www1.artemis.native_app.core.ui.R as CoreUiR @@ -58,7 +53,6 @@ class ExerciseOverviewE2eTest : BaseExerciseTest() { ) } - @OptIn(KoinInternalApi::class) private fun setupUiAndViewModel( onViewTextExerciseParticipationScreen: (participationId: Long) -> Unit = {} ): ExerciseViewModel { @@ -74,22 +68,16 @@ class ExerciseOverviewE2eTest : BaseExerciseTest() { ) composeTestRule.setContent { - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - ExerciseScreen( - modifier = Modifier.fillMaxSize(), - viewModel = viewModel, - navController = rememberNavController(), - onNavigateBack = { }, - onViewResult = { }, - onViewTextExerciseParticipationScreen = onViewTextExerciseParticipationScreen, - onParticipateInQuiz = { _, _ -> }, - onClickViewQuizResults = { } - ) - } + ExerciseScreen( + modifier = Modifier.fillMaxSize(), + viewModel = viewModel, + navController = rememberNavController(), + onNavigateBack = { }, + onViewResult = { }, + onViewTextExerciseParticipationScreen = onViewTextExerciseParticipationScreen, + onParticipateInQuiz = { _, _ -> }, + onClickViewQuizResults = { } + ) } return viewModel diff --git a/feature/lecture-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lecture_view/LectureE2eTest.kt b/feature/lecture-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lecture_view/LectureE2eTest.kt index 584e30e1b..6954ef03f 100644 --- a/feature/lecture-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lecture_view/LectureE2eTest.kt +++ b/feature/lecture-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/lecture_view/LectureE2eTest.kt @@ -1,7 +1,6 @@ package de.tum.informatics.www1.artemis.native_app.feature.lecture_view import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.hasParent @@ -55,10 +54,6 @@ import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith import org.koin.android.ext.koin.androidContext -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi -import org.koin.mp.KoinPlatformTools import org.koin.test.KoinTestRule import org.koin.test.get import org.robolectric.RobolectricTestRunner @@ -233,7 +228,6 @@ class LectureE2eTest : BaseComposeTest() { } } - @OptIn(KoinInternalApi::class) private fun setupViewModelAndUi(): LectureViewModel { val viewModel = LectureViewModel( lectureId = lecture.id!!, @@ -249,25 +243,19 @@ class LectureE2eTest : BaseComposeTest() { ) composeTestRule.setContent { - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - LectureScreen( - modifier = Modifier.fillMaxSize(), - courseId = course.id!!, - lectureId = lecture.id!!, - viewModel = viewModel, - navController = rememberNavController(), - onNavigateBack = { }, - onViewExercise = {}, - onNavigateToExerciseResultView = {}, - onNavigateToTextExerciseParticipation = { _, _ -> }, - onParticipateInQuiz = { _, _ -> }, - onClickViewQuizResults = { _, _ -> } - ) - } + LectureScreen( + modifier = Modifier.fillMaxSize(), + courseId = course.id!!, + lectureId = lecture.id!!, + viewModel = viewModel, + navController = rememberNavController(), + onNavigateBack = { }, + onViewExercise = {}, + onNavigateToExerciseResultView = {}, + onNavigateToTextExerciseParticipation = { _, _ -> }, + onParticipateInQuiz = { _, _ -> }, + onClickViewQuizResults = { _, _ -> } + ) } composeTestRule.waitUntilAtLeastOneExists( diff --git a/feature/login/src/test/java/de/tum/informatics/www1/artemis/native_app/feature/login/login_moduleTest.kt b/feature/login/src/test/java/de/tum/informatics/www1/artemis/native_app/feature/login/login_moduleTest.kt index 5fddfd186..6d295a2f2 100644 --- a/feature/login/src/test/java/de/tum/informatics/www1/artemis/native_app/feature/login/login_moduleTest.kt +++ b/feature/login/src/test/java/de/tum/informatics/www1/artemis/native_app/feature/login/login_moduleTest.kt @@ -1,92 +1,43 @@ package de.tum.informatics.www1.artemis.native_app.feature.login -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.test.junit4.ComposeContentTestRule -import androidx.lifecycle.ViewModel -import androidx.test.platform.app.InstrumentationRegistry -import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis +import androidx.lifecycle.SavedStateHandle import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest -import de.tum.informatics.www1.artemis.native_app.core.test.BaseComposeTest -import de.tum.informatics.www1.artemis.native_app.core.test.coreTestModules -import de.tum.informatics.www1.artemis.native_app.feature.login.custom_instance_selection.CustomInstanceSelectionViewModel -import de.tum.informatics.www1.artemis.native_app.feature.login.login.LoginViewModel -import de.tum.informatics.www1.artemis.native_app.feature.login.register.RegisterViewModel +import de.tum.informatics.www1.artemis.native_app.core.datastore.AccountService +import de.tum.informatics.www1.artemis.native_app.core.datastore.ServerConfigurationService +import de.tum.informatics.www1.artemis.native_app.core.device.NetworkStatusProvider import de.tum.informatics.www1.artemis.native_app.feature.login.saml2_login.Saml2LoginViewModel -import de.tum.informatics.www1.artemis.native_app.feature.push.pushModule -import org.junit.Rule +import de.tum.informatics.www1.artemis.native_app.feature.login.service.network.ServerProfileInfoService +import de.tum.informatics.www1.artemis.native_app.feature.push.service.PushNotificationConfigurationService import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith -import org.koin.android.ext.koin.androidContext -import org.koin.androidx.compose.koinViewModel -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi -import org.koin.core.parameter.ParametersDefinition -import org.koin.core.parameter.parametersOf -import org.koin.mp.KoinPlatformTools -import org.koin.test.KoinTestRule +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.test.verify.definition +import org.koin.test.verify.verify import org.robolectric.RobolectricTestRunner +import kotlin.coroutines.CoroutineContext @RunWith(RobolectricTestRunner::class) @Category(UnitTest::class) -internal class login_moduleTest : BaseComposeTest() { - - @get:Rule - val koinTestRule = KoinTestRule.create { - androidContext(InstrumentationRegistry.getInstrumentation().context) - - modules(coreTestModules) - modules(loginModule, pushModule) - } - - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the loginModule initializes AccountViewModel without errors`() { - composeTestRule.testViewModelInitialization() - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the loginModule initializes LoginViewModel without errors`() { - composeTestRule.testViewModelInitialization() - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the loginModule initializes RegisterViewModel without errors`() { - composeTestRule.testViewModelInitialization() - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the loginModule initializes CustomInstanceSelectionViewModel without errors`() { - composeTestRule.testViewModelInitialization() - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the loginModule initializes Saml2LoginViewModel without errors`() { - composeTestRule.testViewModelInitialization { - parametersOf(true) // rememberMe - } - } - - /** - * Test if a ViewModel can be initialized without errors. - * @param parameters The parameters to pass to the ViewModel constructor - */ - @OptIn(KoinInternalApi::class) - private inline fun ComposeContentTestRule.testViewModelInitialization( - noinline parameters: ParametersDefinition? = null - ) { - setContent { - // This is a workaround to make koin work in tests. - // See: https://github.com/InsertKoinIO/koin/issues/1557#issue-1660665501 - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - koinViewModel(parameters = parameters) - } - } +internal class login_moduleTest { + + @OptIn(KoinExperimentalAPI::class) + @Test + fun checkKoinModule() { + loginModule.verify( + injections = listOf( + definition(Boolean::class) // rememberMe + ), + extraTypes = listOf( + ServerConfigurationService::class, + NetworkStatusProvider::class, + SavedStateHandle::class, + PushNotificationConfigurationService::class, + ServerProfileInfoService::class, + AccountService::class, + CoroutineContext::class, + ) + ) } } \ No newline at end of file diff --git a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/manage_conversations_moduleTest.kt b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/manage_conversations_moduleTest.kt index 92518ceba..6fb9ded0d 100644 --- a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/manage_conversations_moduleTest.kt +++ b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/manage_conversations_moduleTest.kt @@ -1,14 +1,16 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations import android.app.Application -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.test.junit4.ComposeContentTestRule -import androidx.lifecycle.ViewModel -import androidx.test.platform.app.InstrumentationRegistry -import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis +import androidx.lifecycle.SavedStateHandle +import de.tum.informatics.www1.artemis.native_app.core.common.CurrentActivityListener import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest -import de.tum.informatics.www1.artemis.native_app.core.test.BaseComposeTest -import de.tum.informatics.www1.artemis.native_app.core.test.coreTestModules +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.AccountDataService +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.CourseService +import de.tum.informatics.www1.artemis.native_app.core.datastore.AccountService +import de.tum.informatics.www1.artemis.native_app.core.datastore.ServerConfigurationService +import de.tum.informatics.www1.artemis.native_app.core.device.NetworkStatusProvider +import de.tum.informatics.www1.artemis.native_app.core.websocket.WebsocketProvider +import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.service.storage.ConversationPreferenceService import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.browse_channels.BrowseChannelsViewModel import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.create_channel.CreateChannelViewModel import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.create_personal_conversation.CreatePersonalConversationViewModel @@ -16,106 +18,47 @@ import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversati import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.settings.add_members.ConversationAddMembersViewModel import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.settings.members.ConversationMembersViewModel import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.settings.overview.ConversationSettingsViewModel -import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.sharedConversationModule -import org.junit.Rule +import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.service.network.ConversationService import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith -import org.koin.android.ext.koin.androidContext -import org.koin.androidx.compose.koinViewModel -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi -import org.koin.core.parameter.ParametersDefinition -import org.koin.core.parameter.parametersOf -import org.koin.mp.KoinPlatformTools -import org.koin.test.KoinTestRule +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.test.verify.definition +import org.koin.test.verify.verify import org.robolectric.RobolectricTestRunner +import kotlin.coroutines.CoroutineContext @RunWith(RobolectricTestRunner::class) @Category(UnitTest::class) -internal class manage_conversations_moduleTest : BaseComposeTest() { +internal class manage_conversations_moduleTest { - @get:Rule - val koinTestRule = KoinTestRule.create { - androidContext(InstrumentationRegistry.getInstrumentation().context) - - modules(coreTestModules) - modules(manageConversationsModule, sharedConversationModule) - } - - private val courseId = 1L - private val conversationId = 22L - private val testContext = context.applicationContext as Application - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the manage_conversations_module initializes ConversationOverviewViewModel without errors`() { - composeTestRule.testViewModelInitialization() { - parametersOf(testContext, courseId) - } - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the manage_conversations_module initializes CreatePersonalConversationViewModel without errors`() { - composeTestRule.testViewModelInitialization() { - parametersOf(courseId) - } - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the manage_conversations_module initializes CreateChannelViewModel without errors`() { - composeTestRule.testViewModelInitialization() { - parametersOf(courseId) - } - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the manage_conversations_module initializes BrowseChannelsViewModel without errors`() { - composeTestRule.testViewModelInitialization() { - parametersOf(courseId) - } - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the manage_conversations_module initializes ConversationSettingsViewModel without errors`() { - composeTestRule.testViewModelInitialization { - parametersOf(courseId, conversationId) - } - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the manage_conversations_module initializes ConversationMembersViewModel without errors`() { - composeTestRule.testViewModelInitialization { - parametersOf(courseId, conversationId) - } - } - - @Test(timeout = DefaultTestTimeoutMillis) - fun `the manage_conversations_module initializes ConversationAddMembersViewModel without errors`() { - composeTestRule.testViewModelInitialization { - parametersOf(courseId, conversationId) - } - } - - /** - * Test if a ViewModel can be initialized without errors. - * @param parameters The parameters to pass to the ViewModel constructor - */ - @OptIn(KoinInternalApi::class) - private inline fun ComposeContentTestRule.testViewModelInitialization( - noinline parameters: ParametersDefinition? = null - ) { - setContent { - // This is a workaround to make koin work in tests. - // See: https://github.com/InsertKoinIO/koin/issues/1557#issue-1660665501 - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - koinViewModel(parameters = parameters) - } - } + @OptIn(KoinExperimentalAPI::class) + @Test + fun checkKoinModule() { + manageConversationsModule.verify( + injections = listOf( + definition(Application::class, String::class), + definition(Long::class), + definition(Long::class), + definition(Long::class), + definition(Long::class, Long::class), + definition(Long::class, Long::class), + definition(Long::class, Long::class), + ), + extraTypes = listOf( + ServerConfigurationService::class, + NetworkStatusProvider::class, + WebsocketProvider::class, + AccountService::class, + AccountDataService::class, + ConversationPreferenceService::class, + ConversationService::class, + CourseService::class, + CoroutineContext::class, + CurrentActivityListener::class, + SavedStateHandle::class, + ) + ) } } \ No newline at end of file diff --git a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/members/ConversationMemberSettingsE2eTest.kt b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/members/ConversationMemberSettingsE2eTest.kt index 18a695de0..a572c1756 100644 --- a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/members/ConversationMemberSettingsE2eTest.kt +++ b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/members/ConversationMemberSettingsE2eTest.kt @@ -1,7 +1,6 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.members import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assert @@ -31,10 +30,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.metistest.Conversation import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi -import org.koin.mp.KoinPlatformTools import org.koin.test.get import org.robolectric.RobolectricTestRunner import kotlin.time.Duration.Companion.seconds @@ -188,7 +183,6 @@ class ConversationMemberSettingsE2eTest : ConversationBaseTest() { ) } - @OptIn(KoinInternalApi::class) private fun setupUiAndViewModel() { val viewModel = ConversationMembersViewModel( initialCourseId = course.id!!, @@ -203,18 +197,12 @@ class ConversationMemberSettingsE2eTest : ConversationBaseTest() { ) composeTestRule.setContent { - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - ConversationMembersBody( - modifier = Modifier.fillMaxSize(), - courseId = course.id!!, - conversationId = channel.id, - viewModel = viewModel - ) - } + ConversationMembersBody( + modifier = Modifier.fillMaxSize(), + courseId = course.id!!, + conversationId = channel.id, + viewModel = viewModel + ) } testDispatcher.scheduler.advanceTimeBy(2.seconds) diff --git a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/ConversationSettingsBaseE2eTest.kt b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/ConversationSettingsBaseE2eTest.kt index 6a507cb13..8a771fb5e 100644 --- a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/ConversationSettingsBaseE2eTest.kt +++ b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/ConversationSettingsBaseE2eTest.kt @@ -1,7 +1,6 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.settings import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.hasSetTextAction @@ -20,10 +19,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversati import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.Conversation import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.service.network.getConversation import de.tum.informatics.www1.artemis.native_app.feature.metistest.ConversationBaseTest -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi -import org.koin.mp.KoinPlatformTools import org.koin.test.get import kotlin.test.assertIs @@ -97,7 +92,6 @@ internal abstract class ConversationSettingsBaseE2eTest : ConversationBaseTest() .performTextInput(newText) } - @OptIn(KoinInternalApi::class) protected fun setupUiAndViewModel( conversation: Conversation, onConversationLeft: () -> Unit = {} @@ -115,22 +109,16 @@ internal abstract class ConversationSettingsBaseE2eTest : ConversationBaseTest() ) composeTestRule.setContent { - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - ConversationSettingsScreen( - modifier = Modifier.fillMaxSize(), - courseId = course.id!!, - conversationId = conversation.id, - viewModel = viewModel, - onNavigateBack = { }, - onRequestAddMembers = { }, - onRequestViewAllMembers = { }, - onConversationLeft = onConversationLeft - ) - } + ConversationSettingsScreen( + modifier = Modifier.fillMaxSize(), + courseId = course.id!!, + conversationId = conversation.id, + viewModel = viewModel, + onNavigateBack = { }, + onRequestAddMembers = { }, + onRequestViewAllMembers = { }, + onConversationLeft = onConversationLeft + ) } return viewModel diff --git a/feature/metis/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/communication_moduleTest.kt b/feature/metis/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/communication_moduleTest.kt new file mode 100644 index 000000000..c87026632 --- /dev/null +++ b/feature/metis/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/communication_moduleTest.kt @@ -0,0 +1,61 @@ +package de.tum.informatics.www1.artemis.native_app.feature.metis + +import android.app.Application +import android.content.Context +import androidx.lifecycle.SavedStateHandle +import androidx.work.WorkerParameters +import de.tum.informatics.www1.artemis.native_app.core.common.CurrentActivityListener +import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.AccountDataService +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.CourseService +import de.tum.informatics.www1.artemis.native_app.core.datastore.AccountService +import de.tum.informatics.www1.artemis.native_app.core.datastore.ServerConfigurationService +import de.tum.informatics.www1.artemis.native_app.core.device.NetworkStatusProvider +import de.tum.informatics.www1.artemis.native_app.core.websocket.WebsocketProvider +import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.StandalonePostId +import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.service.network.ConversationService +import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.ui.profile_picture.UserProfileDialogViewModel +import de.tum.informatics.www1.artemis.native_app.feature.metis.ui.NavigateToUserConversationViewModel +import de.tum.informatics.www1.artemis.native_app.feature.metis.ui.SinglePageConversationBodyViewModel +import org.junit.Test +import org.junit.experimental.categories.Category +import org.junit.runner.RunWith +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.test.verify.definition +import org.koin.test.verify.verify +import org.robolectric.RobolectricTestRunner +import kotlin.coroutines.CoroutineContext + +@RunWith(RobolectricTestRunner::class) +@Category(UnitTest::class) +internal class communication_moduleTest { + + @OptIn(KoinExperimentalAPI::class) + @Test + fun checkKoinModule() { + communicationModule.verify( + injections = listOf( + definition(Long::class, String::class), + definition(Long::class), + definition(Long::class, Long::class), + ), + extraTypes = listOf( + ServerConfigurationService::class, + NetworkStatusProvider::class, + WebsocketProvider::class, + AccountService::class, + AccountDataService::class, + CoroutineContext::class, + ConversationService::class, + CourseService::class, + Long::class, + Context::class, + WorkerParameters::class, + StandalonePostId::class, + Application::class, + CurrentActivityListener::class, + SavedStateHandle::class, + ) + ) + } +} \ No newline at end of file diff --git a/feature/push/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/push/PushNotificationSettingsE2eTest.kt b/feature/push/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/push/PushNotificationSettingsE2eTest.kt index 8b07cd608..3f345b5a3 100644 --- a/feature/push/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/push/PushNotificationSettingsE2eTest.kt +++ b/feature/push/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/push/PushNotificationSettingsE2eTest.kt @@ -1,7 +1,6 @@ package de.tum.informatics.www1.artemis.native_app.feature.push import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.hasAnyAncestor @@ -41,11 +40,7 @@ import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith import org.koin.android.ext.koin.androidContext -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi import org.koin.dsl.module -import org.koin.mp.KoinPlatformTools import org.koin.test.KoinTestRule import org.koin.test.get import org.robolectric.RobolectricTestRunner @@ -203,7 +198,6 @@ class PushNotificationSettingsE2eTest : BaseComposeTest() { } } - @OptIn(KoinInternalApi::class) private fun setupUiAndViewModel(): PushNotificationSettingsViewModel { val viewModel = PushNotificationSettingsViewModel( notificationSettingsService = get(), @@ -215,16 +209,10 @@ class PushNotificationSettingsE2eTest : BaseComposeTest() { ) composeTestRule.setContent { - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - PushNotificationSettingsUi( - modifier = Modifier.fillMaxSize(), - viewModel = viewModel - ) - } + PushNotificationSettingsUi( + modifier = Modifier.fillMaxSize(), + viewModel = viewModel + ) } return viewModel diff --git a/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizBaseE2eTest.kt b/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizBaseE2eTest.kt index 3276f1aee..737e5919d 100644 --- a/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizBaseE2eTest.kt +++ b/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizBaseE2eTest.kt @@ -1,7 +1,6 @@ package de.tum.informatics.www1.artemis.native_app.feature.quiz import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.lifecycle.SavedStateHandle import de.tum.informatics.www1.artemis.native_app.core.data.service.network.ParticipationService import de.tum.informatics.www1.artemis.native_app.core.model.Course @@ -19,10 +18,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.quiz.service.QuizExerc import org.junit.Before import org.junit.Rule import org.koin.android.ext.koin.androidContext -import org.koin.compose.LocalKoinApplication -import org.koin.compose.LocalKoinScope -import org.koin.core.annotation.KoinInternalApi -import org.koin.mp.KoinPlatformTools import org.koin.test.KoinTestRule import org.koin.test.get import org.robolectric.shadows.ShadowLog @@ -62,7 +57,6 @@ internal abstract class QuizBaseE2eTest(protected val quizType: QuizType.Workabl open suspend fun setupHook() {} - @OptIn(KoinInternalApi::class) protected fun setupUi(exerciseId: Long, content: @Composable (QuizParticipationViewModel) -> Unit): QuizParticipationViewModel { val viewModel = QuizParticipationViewModel( courseId = courseId, @@ -80,13 +74,7 @@ internal abstract class QuizBaseE2eTest(protected val quizType: QuizType.Workabl ) composeTestRule.setContent { - CompositionLocalProvider( - LocalKoinScope provides KoinPlatformTools.defaultContext() - .get().scopeRegistry.rootScope, - LocalKoinApplication provides KoinPlatformTools.defaultContext().get() - ) { - content(viewModel) - } + content(viewModel) } return viewModel diff --git a/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/quiz_participation_moduleTest.kt b/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/quiz_participation_moduleTest.kt new file mode 100644 index 000000000..8599e75da --- /dev/null +++ b/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/quiz_participation_moduleTest.kt @@ -0,0 +1,52 @@ +package de.tum.informatics.www1.artemis.native_app.feature.quiz + +import androidx.lifecycle.SavedStateHandle +import de.tum.informatics.www1.artemis.native_app.core.common.test.UnitTest +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.ExerciseService +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.ParticipationService +import de.tum.informatics.www1.artemis.native_app.core.data.service.network.ServerTimeService +import de.tum.informatics.www1.artemis.native_app.core.datastore.AccountService +import de.tum.informatics.www1.artemis.native_app.core.datastore.ServerConfigurationService +import de.tum.informatics.www1.artemis.native_app.core.device.NetworkStatusProvider +import de.tum.informatics.www1.artemis.native_app.core.websocket.WebsocketProvider +import de.tum.informatics.www1.artemis.native_app.feature.quiz.participation.QuizParticipationViewModel +import de.tum.informatics.www1.artemis.native_app.feature.quiz.service.QuizExerciseService +import de.tum.informatics.www1.artemis.native_app.feature.quiz.service.QuizParticipationService +import de.tum.informatics.www1.artemis.native_app.feature.quiz.view_result.QuizResultViewModel +import org.junit.Test +import org.junit.experimental.categories.Category +import org.junit.runner.RunWith +import org.koin.core.annotation.KoinExperimentalAPI +import org.koin.test.verify.definition +import org.koin.test.verify.verify +import org.robolectric.RobolectricTestRunner +import kotlin.coroutines.CoroutineContext + +@RunWith(RobolectricTestRunner::class) +@Category(UnitTest::class) +internal class quiz_participation_moduleTest { + + @OptIn(KoinExperimentalAPI::class) + @Test + fun checkKoinModule() { + quizParticipationModule.verify( + injections = listOf( + definition(Long::class, Long::class, QuizType.WorkableQuizType::class), + definition(Long::class, QuizType.ViewableQuizType::class) + ), + extraTypes = listOf( + SavedStateHandle::class, + ServerConfigurationService::class, + NetworkStatusProvider::class, + AccountService::class, + CoroutineContext::class, + ExerciseService::class, + QuizExerciseService::class, + QuizParticipationService::class, + WebsocketProvider::class, + ParticipationService::class, + ServerTimeService::class + ) + ) + } +} \ No newline at end of file