diff --git a/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/BaseComposeTest.kt b/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/BaseComposeTest.kt index a71a648ad..5bbeab22f 100644 --- a/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/BaseComposeTest.kt +++ b/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/BaseComposeTest.kt @@ -21,9 +21,18 @@ abstract class BaseComposeTest : KoinTest { protected val context: Context get() = InstrumentationRegistry.getInstrumentation().context - fun runBlockingWithTestTimeout(block: suspend () -> T): T { + /** + * Run a block of code with a timeout. The default test timeout is multiplied by the + * given [timeoutMultiplier]. + * @param timeoutMultiplier The multiplier for the default test timeout. Can be used to increase + * the timeout for flaky tests + */ + fun runBlockingWithTestTimeout( + timeoutMultiplier: Int = 1, + block: suspend () -> T + ): T { return runBlocking { - withTimeout(DefaultTimeoutMillis) { + withTimeout(DefaultTimeoutMillis * timeoutMultiplier) { block() } } diff --git a/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/test_setup/TestVariables.kt b/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/test_setup/TestVariables.kt index af73193f5..dbc20f4f4 100644 --- a/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/test_setup/TestVariables.kt +++ b/core/core-test/src/main/kotlin/de/tum/informatics/www1/artemis/native_app/core/test/test_setup/TestVariables.kt @@ -1,3 +1,3 @@ package de.tum.informatics.www1.artemis.native_app.core.test.test_setup -val DefaultTimeoutMillis: Long get() = System.getenv("DEFAULT_TIMEOUT")?.toLong() ?: 15000L \ No newline at end of file +val DefaultTimeoutMillis: Long get() = System.getenv("DEFAULT_TIMEOUT")?.toLong() ?: 10000L \ No newline at end of file diff --git a/feature/course-registration/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseregistration/CourseRegistrationE2eTest.kt b/feature/course-registration/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseregistration/CourseRegistrationE2eTest.kt index 9973ba91b..1e34cda5f 100644 --- a/feature/course-registration/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseregistration/CourseRegistrationE2eTest.kt +++ b/feature/course-registration/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseregistration/CourseRegistrationE2eTest.kt @@ -1,37 +1,33 @@ package de.tum.informatics.www1.artemis.native_app.feature.courseregistration -import android.content.Context import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.ui.Modifier import androidx.compose.ui.test.hasParent import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.hasText -import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollToKey import androidx.test.platform.app.InstrumentationRegistry +import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.model.Course +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.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createCourse import de.tum.informatics.www1.artemis.native_app.feature.login.loginModule import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken import de.tum.informatics.www1.artemis.native_app.feature.login.test.performTestLogin import de.tum.informatics.www1.artemis.native_app.feature.login.test.testLoginModule -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.withTimeout import org.junit.Before import org.junit.Rule 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.test.KoinTest import org.koin.test.KoinTestRule import org.koin.test.get import org.robolectric.RobolectricTestRunner @@ -39,12 +35,7 @@ import kotlin.test.assertEquals @Category(EndToEndTest::class) @RunWith(RobolectricTestRunner::class) -class CourseRegistrationE2eTest : KoinTest { - - private val context: Context get() = InstrumentationRegistry.getInstrumentation().context - - @get:Rule - val composeTestRule = createComposeRule() +class CourseRegistrationE2eTest : BaseComposeTest() { @get:Rule val koinTestRule = KoinTestRule.create { @@ -58,11 +49,9 @@ class CourseRegistrationE2eTest : KoinTest { @Before fun setup() { - runBlocking { - withTimeout(DefaultTimeoutMillis) { - performTestLogin() - course = createCourse(getAdminAccessToken(), forceSelfRegistration = true) - } + runBlockingWithTestTimeout { + performTestLogin() + course = createCourse(getAdminAccessToken(), forceSelfRegistration = true) } } 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 e575ee01b..31c810471 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,16 +1,14 @@ package de.tum.informatics.www1.artemis.native_app.feature.courseview -import android.content.Context import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier -import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.platform.app.InstrumentationRegistry import de.tum.informatics.www1.artemis.native_app.core.model.Course +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.test.test_setup.DefaultTimeoutMillis -import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createCourse import de.tum.informatics.www1.artemis.native_app.core.test.testWebsocketModule +import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createCourse import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.CourseViewModel import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.CourseUiScreen import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.course_overview.DEFAULT_CONVERSATION_ID @@ -19,9 +17,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.login.loginModule import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken import de.tum.informatics.www1.artemis.native_app.feature.login.test.performTestLogin import de.tum.informatics.www1.artemis.native_app.feature.login.test.testLoginModule -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.withTimeout import org.junit.Before import org.junit.Rule import org.koin.android.ext.koin.androidContext @@ -29,16 +24,10 @@ 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.KoinTest import org.koin.test.KoinTestRule import org.koin.test.get -abstract class BaseCourseTest : KoinTest { - - protected val testDispatcher = UnconfinedTestDispatcher() - - @get:Rule - val composeTestRule = createComposeRule() +abstract class BaseCourseTest : BaseComposeTest() { @get:Rule val koinTestRule = KoinTestRule.create { @@ -50,16 +39,11 @@ abstract class BaseCourseTest : KoinTest { lateinit var course: Course - val context: Context get() = InstrumentationRegistry.getInstrumentation().context - @Before fun setup() { - runBlocking { - withTimeout(DefaultTimeoutMillis) { - performTestLogin() - - course = createCourse(getAdminAccessToken()) - } + runBlockingWithTestTimeout { + performTestLogin() + course = createCourse(getAdminAccessToken()) } } diff --git a/feature/course-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ExerciseListOverviewE2eTest.kt b/feature/course-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ExerciseListOverviewE2eTest.kt index 335079cfe..2b9baf652 100644 --- a/feature/course-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ExerciseListOverviewE2eTest.kt +++ b/feature/course-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/courseview/ExerciseListOverviewE2eTest.kt @@ -5,9 +5,9 @@ import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performScrollToKey +import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.model.exercise.Exercise -import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createExercise import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createModelingExercise @@ -15,8 +15,6 @@ import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_cr import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createTextExercise import de.tum.informatics.www1.artemis.native_app.feature.courseview.ui.exercise_list.TEST_TAG_EXERCISE_LIST_LAZY_COLUMN import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import org.junit.Ignore import org.junit.Test import org.junit.experimental.categories.Category @@ -80,10 +78,8 @@ class ExerciseListOverviewE2eTest : BaseCourseTest() { private fun displayExerciseTypeTestImpl(createExercise: suspend () -> Exercise) { - val exercise = runBlocking { - withTimeout(DefaultTimeoutMillis) { - createExercise() - } + val exercise = runBlockingWithTestTimeout { + createExercise() } setupAndDisplayCourseUi() diff --git a/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/BaseExerciseTest.kt b/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/BaseExerciseTest.kt index b31059d8e..399f9858c 100644 --- a/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/BaseExerciseTest.kt +++ b/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/BaseExerciseTest.kt @@ -1,39 +1,26 @@ package de.tum.informatics.www1.artemis.native_app.feature.exercise_view.participate.text_exercise -import android.content.Context -import androidx.compose.ui.test.junit4.createComposeRule import androidx.test.platform.app.InstrumentationRegistry import de.tum.informatics.www1.artemis.native_app.core.model.Course import de.tum.informatics.www1.artemis.native_app.core.model.exercise.TextExercise +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.test.test_setup.DefaultTimeoutMillis +import de.tum.informatics.www1.artemis.native_app.core.test.testWebsocketModule import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createCourse import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createExercise import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createTextExercise -import de.tum.informatics.www1.artemis.native_app.core.test.testWebsocketModule import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.exerciseModule import de.tum.informatics.www1.artemis.native_app.feature.login.loginModule import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken import de.tum.informatics.www1.artemis.native_app.feature.login.test.performTestLogin import de.tum.informatics.www1.artemis.native_app.feature.login.test.testLoginModule -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.withTimeout import org.junit.Before import org.junit.Rule import org.koin.android.ext.koin.androidContext -import org.koin.test.KoinTest import org.koin.test.KoinTestRule import org.robolectric.shadows.ShadowLog -abstract class BaseExerciseTest : KoinTest { - - protected val testDispatcher = UnconfinedTestDispatcher() - - protected val context: Context get() = InstrumentationRegistry.getInstrumentation().context - - @get:Rule - val composeTestRole = createComposeRule() +abstract class BaseExerciseTest : BaseComposeTest() { @get:Rule val koinTestRule = KoinTestRule.create { @@ -52,18 +39,16 @@ abstract class BaseExerciseTest : KoinTest { open fun setup() { ShadowLog.stream = System.out - runBlocking { - withTimeout(DefaultTimeoutMillis) { - accessToken = performTestLogin() + runBlockingWithTestTimeout { + accessToken = performTestLogin() - course = createCourse(getAdminAccessToken()) - exercise = createExercise( - getAdminAccessToken(), - course.id!!, - endpoint = "text-exercises", - creator = ::createTextExercise - ) as TextExercise - } + course = createCourse(getAdminAccessToken()) + exercise = createExercise( + getAdminAccessToken(), + course.id!!, + endpoint = "text-exercises", + creator = ::createTextExercise + ) as TextExercise } } } \ 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 3296a2ae9..8b395d1cb 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 @@ -10,8 +10,8 @@ import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.navigation.compose.rememberNavController -import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis +import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.ExerciseViewModel import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.home.ExerciseScreen @@ -34,7 +34,7 @@ class ExerciseOverviewE2eTest : BaseExerciseTest() { fun `displays correct exercise data`() { setupUiAndViewModel() - composeTestRole.onAllNodesWithText(exercise.title!!).onFirst().assertExists() + composeTestRule.onAllNodesWithText(exercise.title!!).onFirst().assertExists() } @OptIn(ExperimentalTestApi::class) @@ -44,14 +44,14 @@ class ExerciseOverviewE2eTest : BaseExerciseTest() { setupUiAndViewModel { participationId = it } - composeTestRole.onNodeWithText( + composeTestRule.onNodeWithText( context.getString(CoreUiR.string.exercise_actions_start_exercise_button) ) .performClick() - composeTestRole.waitUntil(DefaultTimeoutMillis) { participationId != null } + composeTestRule.waitUntil(DefaultTimeoutMillis) { participationId != null } - composeTestRole + composeTestRule .waitUntilExactlyOneExists( hasText(context.getString(CoreUiR.string.exercise_actions_open_exercise_button)), DefaultTimeoutMillis @@ -73,7 +73,7 @@ class ExerciseOverviewE2eTest : BaseExerciseTest() { coroutineContext = testDispatcher ) - composeTestRole.setContent { + composeTestRule.setContent { CompositionLocalProvider( LocalKoinScope provides KoinPlatformTools.defaultContext() .get().scopeRegistry.rootScope, diff --git a/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/TextExerciseParticipationE2eTest.kt b/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/TextExerciseParticipationE2eTest.kt index 386508415..ed8699ef8 100644 --- a/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/TextExerciseParticipationE2eTest.kt +++ b/feature/exercise-view/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/exercise_view/participate/text_exercise/TextExerciseParticipationE2eTest.kt @@ -10,25 +10,24 @@ import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performTextInput +import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest +import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl import de.tum.informatics.www1.artemis.native_app.core.data.service.network.CourseExerciseService import de.tum.informatics.www1.artemis.native_app.core.model.exercise.participation.Participation import de.tum.informatics.www1.artemis.native_app.core.model.exercise.participation.StudentParticipation import de.tum.informatics.www1.artemis.native_app.core.model.exercise.submission.SubmissionType import de.tum.informatics.www1.artemis.native_app.core.model.exercise.submission.TextSubmission -import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis -import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.R -import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.service.TextSubmissionService import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.participate.textexercise.SyncState import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.participate.textexercise.TEST_TAG_TEXT_FIELD_PARTICIPATION import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.participate.textexercise.TextExerciseParticipationScreen import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.participate.textexercise.TextExerciseParticipationViewModel +import de.tum.informatics.www1.artemis.native_app.feature.exerciseview.service.TextSubmissionService import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import kotlinx.coroutines.withTimeoutOrNull import kotlinx.datetime.Clock import org.junit.Before @@ -56,20 +55,18 @@ class TextExerciseParticipationE2eTest : BaseExerciseTest() { @Before override fun setup() { super.setup() - runBlocking { - withTimeout(DefaultTimeoutMillis) { - val courseExerciseService: CourseExerciseService = get() - participation = - courseExerciseService - .startExercise(exercise.id!!, testServerUrl, accessToken) - .orThrow("Start text exercise participation") - - val submissions = participation.submissions - assertNotNull(submissions, "Submissions are not given in participation") - assertFalse(submissions.isEmpty(), "Submissions must not be empty") - - initialSubmission = assertIs(submissions.first()) - } + runBlockingWithTestTimeout { + val courseExerciseService: CourseExerciseService = get() + participation = + courseExerciseService + .startExercise(exercise.id!!, testServerUrl, accessToken) + .orThrow("Start text exercise participation") + + val submissions = participation.submissions + assertNotNull(submissions, "Submissions are not given in participation") + assertFalse(submissions.isEmpty(), "Submissions must not be empty") + + initialSubmission = assertIs(submissions.first()) } } @@ -77,27 +74,26 @@ class TextExerciseParticipationE2eTest : BaseExerciseTest() { fun `can view already entered text`() { val textSubmissionService: TextSubmissionService = get() - runBlocking { - withTimeout(DefaultTimeoutMillis) { - textSubmissionService.update( - TextSubmission( - id = initialSubmission.id, - submissionDate = Clock.System.now(), - participation = StudentParticipation.StudentParticipationImpl(id = participation.id!!), - submitted = true, - text = textToEnter, - submissionType = SubmissionType.MANUAL - ), - exercise.id!!, - testServerUrl, - accessToken - ).orThrow("Could no update text submission to set initial submission") - } + runBlockingWithTestTimeout { + textSubmissionService.update( + TextSubmission( + id = initialSubmission.id, + submissionDate = Clock.System.now(), + participation = StudentParticipation.StudentParticipationImpl(id = participation.id!!), + submitted = true, + text = textToEnter, + submissionType = SubmissionType.MANUAL + ), + exercise.id!!, + testServerUrl, + accessToken + ).orThrow("Could no update text submission to set initial submission") } + setupUi() - composeTestRole + composeTestRule .onNodeWithTag(TEST_TAG_TEXT_FIELD_PARTICIPATION) .assert(hasText(textToEnter)) } @@ -106,11 +102,11 @@ class TextExerciseParticipationE2eTest : BaseExerciseTest() { fun `can update text by entering new text`() { val viewModel = setupUi() - composeTestRole + composeTestRule .onNodeWithTag(TEST_TAG_TEXT_FIELD_PARTICIPATION) .performTextInput(textToEnter) - composeTestRole + composeTestRule .onNodeWithText(context.getString(R.string.participate_text_exercise_submit_button)) .performClick() @@ -123,7 +119,7 @@ class TextExerciseParticipationE2eTest : BaseExerciseTest() { } ?: throw RuntimeException("State could not be synced in time.") } - composeTestRole + composeTestRule .onNodeWithText(context.getString(R.string.participate_text_exercise_synced_changes)) .assertExists() } @@ -140,7 +136,7 @@ class TextExerciseParticipationE2eTest : BaseExerciseTest() { coroutineContext = testDispatcher ) - composeTestRole.setContent { + composeTestRule.setContent { TextExerciseParticipationScreen( modifier = Modifier.fillMaxSize(), viewModel = viewModel, @@ -149,7 +145,7 @@ class TextExerciseParticipationE2eTest : BaseExerciseTest() { ) } - composeTestRole.waitUntilAtLeastOneExists( + composeTestRule.waitUntilAtLeastOneExists( hasTestTag(TEST_TAG_TEXT_FIELD_PARTICIPATION), DefaultTimeoutMillis ) 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 ae2bbe6cb..584e30e1b 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,13 +1,11 @@ package de.tum.informatics.www1.artemis.native_app.feature.lecture_view -import android.content.Context 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 import androidx.compose.ui.test.hasTestTag -import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick @@ -15,6 +13,7 @@ import androidx.compose.ui.test.performScrollToKey import androidx.lifecycle.SavedStateHandle import androidx.navigation.compose.rememberNavController import androidx.test.platform.app.InstrumentationRegistry +import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.data.service.impl.JsonProvider import de.tum.informatics.www1.artemis.native_app.core.data.test.awaitFirstSuccess @@ -22,9 +21,9 @@ import de.tum.informatics.www1.artemis.native_app.core.model.Course import de.tum.informatics.www1.artemis.native_app.core.model.lecture.Lecture import de.tum.informatics.www1.artemis.native_app.core.model.lecture.lecture_units.LectureUnit import de.tum.informatics.www1.artemis.native_app.core.model.lecture.lecture_units.LectureUnitExercise +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.test.testWebsocketModule -import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createAttachment import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createAttachmentUnit @@ -37,19 +36,18 @@ import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_cr import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createTextExercise import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createTextLectureUnit import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createVideoLectureUnit -import de.tum.informatics.www1.artemis.native_app.feature.lectureview.lecture_units.TEST_TAG_CHECKBOX_LECTURE_UNIT_COMPLETED import de.tum.informatics.www1.artemis.native_app.feature.lectureview.LectureScreen import de.tum.informatics.www1.artemis.native_app.feature.lectureview.LectureViewModel +import de.tum.informatics.www1.artemis.native_app.feature.lectureview.R import de.tum.informatics.www1.artemis.native_app.feature.lectureview.TEST_TAG_OVERVIEW_LIST import de.tum.informatics.www1.artemis.native_app.feature.lectureview.getLectureUnitTestTag import de.tum.informatics.www1.artemis.native_app.feature.lectureview.lectureModule +import de.tum.informatics.www1.artemis.native_app.feature.lectureview.lecture_units.TEST_TAG_CHECKBOX_LECTURE_UNIT_COMPLETED import de.tum.informatics.www1.artemis.native_app.feature.login.loginModule import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken import de.tum.informatics.www1.artemis.native_app.feature.login.test.performTestLogin import de.tum.informatics.www1.artemis.native_app.feature.login.test.testLoginModule import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.UnconfinedTestDispatcher -import kotlinx.coroutines.withTimeout import kotlinx.serialization.encodeToString import org.junit.Before import org.junit.Rule @@ -61,24 +59,17 @@ 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.KoinTest import org.koin.test.KoinTestRule import org.koin.test.get import org.robolectric.RobolectricTestRunner import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue -import de.tum.informatics.www1.artemis.native_app.feature.lectureview.R @OptIn(ExperimentalTestApi::class) @Category(EndToEndTest::class) @RunWith(RobolectricTestRunner::class) -class LectureE2eTest : KoinTest { - - private val testDispatcher = UnconfinedTestDispatcher() - - @get:Rule - val composeTestRule = createComposeRule() +class LectureE2eTest : BaseComposeTest() { @get:Rule val koinTestRule = KoinTestRule.create { @@ -88,20 +79,16 @@ class LectureE2eTest : KoinTest { modules(loginModule, lectureModule, testLoginModule, testWebsocketModule) } - private val context: Context get() = InstrumentationRegistry.getInstrumentation().context - private lateinit var course: Course private lateinit var lecture: Lecture @Before fun setup() { - runBlocking { - withTimeout(DefaultTestTimeoutMillis) { - performTestLogin() + runBlockingWithTestTimeout { + performTestLogin() - course = createCourse(getAdminAccessToken()) - lecture = createLecture(getAdminAccessToken(), course.id!!) - } + course = createCourse(getAdminAccessToken()) + lecture = createLecture(getAdminAccessToken(), course.id!!) } } @@ -175,10 +162,8 @@ class LectureE2eTest : KoinTest { assert(attachments.size == 3) { "Expected 3 lecture units" } val viewModel = setupViewModelAndUi() - val loadedAttachments = runBlocking { - withTimeout(DefaultTimeoutMillis) { - viewModel.lectureDataState.awaitFirstSuccess("Lecture Data State").attachments - } + val loadedAttachments = runBlockingWithTestTimeout { + viewModel.lectureDataState.awaitFirstSuccess("Lecture Data State").attachments } assertEquals(loadedAttachments.size, 3, "Expected 3 attachments") diff --git a/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ConversationMessagesBaseTest.kt b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ConversationMessagesBaseTest.kt index de8f24e65..6da5e9e2a 100644 --- a/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ConversationMessagesBaseTest.kt +++ b/feature/metis/conversation/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/conversation/ConversationMessagesBaseTest.kt @@ -1,26 +1,21 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.conversation -import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.hasAnyAncestor import androidx.compose.ui.test.hasSetTextAction import androidx.compose.ui.test.hasTestTag -import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl import de.tum.informatics.www1.artemis.native_app.feature.login.test.user2Username -import de.tum.informatics.www1.artemis.native_app.feature.metistest.ConversationBaseTest import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.network.MetisModificationService -import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.MetisContext import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.service.network.MetisService import de.tum.informatics.www1.artemis.native_app.feature.metis.conversation.ui.reply.TEST_TAG_REPLY_TEXT_FIELD +import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.MetisContext import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.DisplayPriority import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.StandalonePost -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout +import de.tum.informatics.www1.artemis.native_app.feature.metistest.ConversationBaseTest import kotlinx.datetime.Clock import org.junit.Before import org.koin.test.get -@OptIn(ExperimentalTestApi::class) abstract class ConversationMessagesBaseTest : ConversationBaseTest() { protected val metisModificationService: MetisModificationService get() = get() @@ -37,17 +32,15 @@ abstract class ConversationMessagesBaseTest : ConversationBaseTest() { override fun setup() { super.setup() - runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversation = conversationService.createOneToOneConversation( - courseId = course.id!!, - partner = user2Username, - authToken = accessToken, - serverUrl = testServerUrl - ).orThrow("Could not create one to one conversation") + runBlockingWithTestTimeout { + conversation = conversationService.createOneToOneConversation( + courseId = course.id!!, + partner = user2Username, + authToken = accessToken, + serverUrl = testServerUrl + ).orThrow("Could not create one to one conversation") - metisContext = MetisContext.Conversation(course.id!!, conversation.id) - } + metisContext = MetisContext.Conversation(course.id!!, conversation.id) } } 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 18223e902..67f15900d 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 @@ -28,8 +28,6 @@ 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.members.testTagForMember import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.ChannelChat import de.tum.informatics.www1.artemis.native_app.feature.metistest.ConversationBaseTest -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith @@ -112,16 +110,14 @@ class ConversationMemberSettingsE2eTest : ConversationBaseTest() { @Test(timeout = DefaultTestTimeoutMillis) fun `can revoke moderation rights`() { - runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversationService.grantModerationRights( - course.id!!, - channel, - user2Username, - accessToken, - testServerUrl - ).orThrow("Could not promote user to moderator") - } + runBlockingWithTestTimeout { + conversationService.grantModerationRights( + course.id!!, + channel, + user2Username, + accessToken, + testServerUrl + ).orThrow("Could not promote user to moderator") } setupUiAndViewModel() diff --git a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/overview/BrowseChannelsE2eTest.kt b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/overview/BrowseChannelsE2eTest.kt index a40d62c6d..f653a92dd 100644 --- a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/overview/BrowseChannelsE2eTest.kt +++ b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/overview/BrowseChannelsE2eTest.kt @@ -8,18 +8,16 @@ import androidx.compose.ui.test.hasText import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo -import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis -import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis +import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl +import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken -import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.ChannelChat import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.browse_channels.BrowseChannelsScreen 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.browse_channels.testTagForBrowsedChannelItem +import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.ChannelChat import de.tum.informatics.www1.artemis.native_app.feature.metistest.ConversationBaseTest -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith @@ -38,19 +36,17 @@ class BrowseChannelsE2eTest : ConversationBaseTest() { override fun setup() { super.setup() - runBlocking { - withTimeout(DefaultTimeoutMillis) { - channels = (0 until 2).map { index -> - conversationService.createChannel( - courseId = course.id!!, - name = "channel$index", - description = "", - isPublic = true, - isAnnouncement = false, - authToken = getAdminAccessToken(), - serverUrl = testServerUrl - ).orThrow("Could not create channel $index") - } + runBlockingWithTestTimeout { + channels = (0 until 2).map { index -> + conversationService.createChannel( + courseId = course.id!!, + name = "channel$index", + description = "", + isPublic = true, + isAnnouncement = false, + authToken = getAdminAccessToken(), + serverUrl = testServerUrl + ).orThrow("Could not create channel $index") } } } @@ -88,10 +84,8 @@ class BrowseChannelsE2eTest : ConversationBaseTest() { composeTestRule.waitUntil(DefaultTimeoutMillis) { navigatedToChannelId != null } assertEquals(channelToJoin.id, navigatedToChannelId, "Joined channel id is not the channel we navigated to") - val conversations = runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversationService.getConversations(course.id!!, accessToken, testServerUrl).orThrow("Could not load conversations") - } + val conversations = runBlockingWithTestTimeout { + conversationService.getConversations(course.id!!, accessToken, testServerUrl).orThrow("Could not load conversations") } assertTrue(conversations.any { it.id == channelToJoin.id }, "Conversations $conversations does not contain the channel we just joined.") diff --git a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/overview/ConversationOverviewE2eTest.kt b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/overview/ConversationOverviewE2eTest.kt index 2897322f8..7bac498fd 100644 --- a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/overview/ConversationOverviewE2eTest.kt +++ b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/overview/ConversationOverviewE2eTest.kt @@ -43,7 +43,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.metistest.Conversation import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import org.junit.Ignore import org.junit.Test import org.junit.experimental.categories.Category @@ -290,13 +289,11 @@ class ConversationOverviewE2eTest : ConversationBaseTest() { ) .performClick() - runBlocking { - withTimeout(DefaultTimeoutMillis) { - viewModel - .conversations - .filter { it.bind { conv -> conv.hidden.isExpanded }.orElse(false) } - .first() - } + runBlockingWithTestTimeout { + viewModel + .conversations + .filter { it.bind { conv -> conv.hidden.isExpanded }.orElse(false) } + .first() } } diff --git a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/ChannelSettingsE2eTest.kt b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/ChannelSettingsE2eTest.kt index ddfaf50ef..9fbb7ff54 100644 --- a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/ChannelSettingsE2eTest.kt +++ b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/ChannelSettingsE2eTest.kt @@ -8,15 +8,13 @@ import androidx.compose.ui.test.isDialog import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo -import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis -import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis +import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl +import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken import de.tum.informatics.www1.artemis.native_app.feature.login.test.user1Username import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.R -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith @@ -34,28 +32,26 @@ internal class ChannelSettingsE2eTest : ConversationSettingsBaseE2eTest() { */ @Test(timeout = DefaultTestTimeoutMillis) fun `can leave channel`() { - val channel = runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversationService.createChannel( - courseId = course.id!!, - name = "clcchannel", - description = "", - isPublic = true, - isAnnouncement = true, - authToken = getAdminAccessToken(), - serverUrl = testServerUrl - ) - .orThrow("Could not create channel") - .apply { - conversationService.registerMembers( - courseId = course.id!!, - conversation = this, - users = listOf(user1Username), - authToken = accessToken, - serverUrl = testServerUrl - ) - } - } + val channel = runBlockingWithTestTimeout { + conversationService.createChannel( + courseId = course.id!!, + name = "clcchannel", + description = "", + isPublic = true, + isAnnouncement = true, + authToken = getAdminAccessToken(), + serverUrl = testServerUrl + ) + .orThrow("Could not create channel") + .apply { + conversationService.registerMembers( + courseId = course.id!!, + conversation = this, + users = listOf(user1Username), + authToken = accessToken, + serverUrl = testServerUrl + ) + } } canLeaveConversationTestImpl(channel) @@ -63,19 +59,17 @@ internal class ChannelSettingsE2eTest : ConversationSettingsBaseE2eTest() { @Test(timeout = DefaultTestTimeoutMillis) fun `can archive channel`() { - val channel = runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversationService.createChannel( - courseId = course.id!!, - name = "cacchannel", - description = "", - isPublic = true, - isAnnouncement = true, - authToken = accessToken, - serverUrl = testServerUrl - ) - .orThrow("Could not create channel") - } + val channel = runBlockingWithTestTimeout { + conversationService.createChannel( + courseId = course.id!!, + name = "cacchannel", + description = "", + isPublic = true, + isAnnouncement = true, + authToken = accessToken, + serverUrl = testServerUrl + ) + .orThrow("Could not create channel") } setupUiAndViewModel(channel) @@ -85,28 +79,26 @@ internal class ChannelSettingsE2eTest : ConversationSettingsBaseE2eTest() { @Test(timeout = DefaultTestTimeoutMillis) fun `can unarchive archived channel`() { - val channel = runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversationService.createChannel( - courseId = course.id!!, - name = "cuacchannel", - description = "", - isPublic = true, - isAnnouncement = true, - authToken = accessToken, - serverUrl = testServerUrl - ) - .orThrow("Could not create channel") - .also { channel -> - conversationService.archiveChannel( - course.id!!, - channel.id, - accessToken, - testServerUrl - ) - .orThrow("could not archive channel") - } - } + val channel = runBlockingWithTestTimeout { + conversationService.createChannel( + courseId = course.id!!, + name = "cuacchannel", + description = "", + isPublic = true, + isAnnouncement = true, + authToken = accessToken, + serverUrl = testServerUrl + ) + .orThrow("Could not create channel") + .also { channel -> + conversationService.archiveChannel( + course.id!!, + channel.id, + accessToken, + testServerUrl + ) + .orThrow("could not archive channel") + } } setupUiAndViewModel(channel) @@ -153,19 +145,17 @@ internal class ChannelSettingsE2eTest : ConversationSettingsBaseE2eTest() { @Test(timeout = DefaultTestTimeoutMillis) fun `can change channel name, description and topic`() { - val channel = runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversationService.createChannel( - courseId = course.id!!, - name = "ccndtchannel", - description = "some description", - isPublic = true, - isAnnouncement = true, - authToken = accessToken, - serverUrl = testServerUrl - ) - .orThrow("Could not create channel") - } + val channel = runBlockingWithTestTimeout { + conversationService.createChannel( + courseId = course.id!!, + name = "ccndtchannel", + description = "some description", + isPublic = true, + isAnnouncement = true, + authToken = accessToken, + serverUrl = testServerUrl + ) + .orThrow("Could not create channel") } val newTitle = "ccndtchannel2" 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 1ed2ae47e..6a507cb13 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 @@ -12,16 +12,14 @@ import androidx.compose.ui.test.performScrollTo import androidx.compose.ui.test.performTextClearance import androidx.compose.ui.test.performTextInput import androidx.lifecycle.SavedStateHandle -import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl +import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.R -import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.service.network.getConversation import de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.ui.conversation.settings.overview.ConversationSettingsScreen 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.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 kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import org.koin.compose.LocalKoinApplication import org.koin.compose.LocalKoinScope import org.koin.core.annotation.KoinInternalApi @@ -52,17 +50,15 @@ internal abstract class ConversationSettingsBaseE2eTest : ConversationBaseTest() composeTestRule .waitUntilDoesNotExist(hasText(context.getString(R.string.conversation_settings_basic_data_save))) - val updatedConversation = runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversationService - .getConversation( - courseId = course.id!!, - conversationId = conversation.id, - authToken = accessToken, - serverUrl = testServerUrl - ) - .orThrow("Could not load updated conversation") - } + val updatedConversation = runBlockingWithTestTimeout { + conversationService + .getConversation( + courseId = course.id!!, + conversationId = conversation.id, + authToken = accessToken, + serverUrl = testServerUrl + ) + .orThrow("Could not load updated conversation") } verifyChanges(assertIs(updatedConversation, "Loaded conversation is not of correct type")) diff --git a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/GroupChatSettingsE2eTest.kt b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/GroupChatSettingsE2eTest.kt index cd0b3a201..43a5aeb48 100644 --- a/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/GroupChatSettingsE2eTest.kt +++ b/feature/metis/manage-conversations/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/metis/manageconversations/settings/GroupChatSettingsE2eTest.kt @@ -1,16 +1,13 @@ package de.tum.informatics.www1.artemis.native_app.feature.metis.manageconversations.settings -import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis -import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis +import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken import de.tum.informatics.www1.artemis.native_app.feature.login.test.user1Username import de.tum.informatics.www1.artemis.native_app.feature.login.test.user2Username import de.tum.informatics.www1.artemis.native_app.feature.login.test.user3Username import de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.GroupChat -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import org.junit.Test import org.junit.experimental.categories.Category import org.junit.runner.RunWith @@ -45,17 +42,15 @@ internal class GroupChatSettingsE2eTest : ConversationSettingsBaseE2eTest() { ) } - private fun createGroupChat(): de.tum.informatics.www1.artemis.native_app.feature.metis.shared.content.dto.conversation.GroupChat { - return runBlocking { - withTimeout(DefaultTimeoutMillis) { - conversationService.createGroupChat( - courseId = course.id!!, - groupMembers = listOf(user1Username, user2Username, user3Username), - authToken = getAdminAccessToken(), - serverUrl = testServerUrl - ) - .orThrow("Could not create group chat") - } + private fun createGroupChat(): GroupChat { + return runBlockingWithTestTimeout { + conversationService.createGroupChat( + courseId = course.id!!, + groupMembers = listOf(user1Username, user2Username, user3Username), + authToken = getAdminAccessToken(), + serverUrl = testServerUrl + ) + .orThrow("Could not create group chat") } } } \ 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 4c853f79c..8b07cd608 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 @@ -10,19 +10,19 @@ import androidx.compose.ui.test.hasTestTag import androidx.compose.ui.test.performClick import androidx.compose.ui.test.performScrollTo import androidx.test.platform.app.InstrumentationRegistry +import de.tum.informatics.www1.artemis.native_app.core.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.common.test.EndToEndTest +import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl import de.tum.informatics.www1.artemis.native_app.core.data.filterSuccess 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.common.test.DefaultTestTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.generateId -import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl import de.tum.informatics.www1.artemis.native_app.feature.login.loginModule import de.tum.informatics.www1.artemis.native_app.feature.login.test.performTestLogin import de.tum.informatics.www1.artemis.native_app.feature.login.test.testLoginModule -import de.tum.informatics.www1.artemis.native_app.feature.push.service.network.NotificationSettingsService import de.tum.informatics.www1.artemis.native_app.feature.push.service.PushNotificationConfigurationService +import de.tum.informatics.www1.artemis.native_app.feature.push.service.network.NotificationSettingsService import de.tum.informatics.www1.artemis.native_app.feature.push.service.network.impl.NotificationSettingsServiceImpl import de.tum.informatics.www1.artemis.native_app.feature.push.ui.PushNotificationSettingsUi import de.tum.informatics.www1.artemis.native_app.feature.push.ui.PushNotificationSettingsViewModel @@ -88,13 +88,11 @@ class PushNotificationSettingsE2eTest : BaseComposeTest() { fun `can retrieve notification settings`() { val viewModel = setupUiAndViewModel() - val currentSettingsByGroup = runBlocking { - withTimeout(DefaultTimeoutMillis) { - viewModel - .currentSettingsByGroup - .filterSuccess() - .first() - } + val currentSettingsByGroup = runBlockingWithTestTimeout { + viewModel + .currentSettingsByGroup + .filterSuccess() + .first() } assertTrue( @@ -124,13 +122,11 @@ class PushNotificationSettingsE2eTest : BaseComposeTest() { fun `can update notification settings`() { val viewModel = setupUiAndViewModel() - val currentSettingsByGroup = runBlocking { - withTimeout(DefaultTimeoutMillis) { - viewModel - .currentSettingsByGroup - .filterSuccess() - .first() - } + val currentSettingsByGroup = runBlockingWithTestTimeout { + viewModel + .currentSettingsByGroup + .filterSuccess() + .first() } Logger.info("CurrentSettingsByGroup=$currentSettingsByGroup") diff --git a/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizParticipationBaseE2eTest.kt b/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizParticipationBaseE2eTest.kt index 8c0d49f03..a3264f663 100644 --- a/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizParticipationBaseE2eTest.kt +++ b/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizParticipationBaseE2eTest.kt @@ -9,6 +9,7 @@ import androidx.compose.ui.test.hasText import androidx.compose.ui.test.isDialog import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl import de.tum.informatics.www1.artemis.native_app.core.data.filterSuccess import de.tum.informatics.www1.artemis.native_app.core.model.exercise.QuizExercise import de.tum.informatics.www1.artemis.native_app.core.model.exercise.submission.QuizSubmission @@ -16,9 +17,8 @@ import de.tum.informatics.www1.artemis.native_app.core.model.exercise.submission import de.tum.informatics.www1.artemis.native_app.core.model.exercise.submission.quiz.MultipleChoiceSubmittedAnswer import de.tum.informatics.www1.artemis.native_app.core.model.exercise.submission.quiz.ShortAnswerSubmittedAnswer import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.DefaultTimeoutMillis -import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createQuizExercise -import de.tum.informatics.www1.artemis.native_app.core.common.test.testServerUrl import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createExerciseFormBodyWithPng +import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.course_creation.createQuizExercise import de.tum.informatics.www1.artemis.native_app.core.test.test_setup.generateId import de.tum.informatics.www1.artemis.native_app.core.ui.common.TEST_TAG_BUTTON_WITH_LOADING_ANIMATION_LOADING import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAccessToken @@ -187,7 +187,9 @@ internal abstract class QuizParticipationBaseE2eTest(quizType: QuizType.Workable ) } - runBlockingWithTestTimeout { + runBlockingWithTestTimeout( + timeoutMultiplier = 2 + ) { setupAndVerify(viewModel) { // Lambda to submit diff --git a/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizWaitingScreenE2eTest.kt b/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizWaitingScreenE2eTest.kt index 4b51ed12f..1baf2cfb3 100644 --- a/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizWaitingScreenE2eTest.kt +++ b/feature/quiz/src/test/kotlin/de/tum/informatics/www1/artemis/native_app/feature/quiz/QuizWaitingScreenE2eTest.kt @@ -23,8 +23,6 @@ import de.tum.informatics.www1.artemis.native_app.feature.login.test.getAdminAcc import de.tum.informatics.www1.artemis.native_app.feature.quiz.participation.QuizParticipationUi import de.tum.informatics.www1.artemis.native_app.feature.quiz.screens.TEST_TAG_TEXT_FIELD_BATCH_PASSWORD import de.tum.informatics.www1.artemis.native_app.feature.quiz.screens.TEST_TAG_WAIT_FOR_QUIZ_START_SCREEN -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withTimeout import org.junit.Ignore import org.junit.Test import org.junit.experimental.categories.Category @@ -86,12 +84,10 @@ internal class QuizWaitingScreenE2eTest : QuizBaseE2eTest(QuizType.Live) { DefaultTimeoutMillis ) - val participation = runBlocking { - withTimeout(DefaultTimeoutMillis) { - participationService - .findParticipation(quiz.id, testServerUrl, accessToken) - .orThrow("Could not load participation. Expected a participation to have been created") - } + val participation = runBlockingWithTestTimeout { + participationService + .findParticipation(quiz.id, testServerUrl, accessToken) + .orThrow("Could not load participation. Expected a participation to have been created") } assertIs(participation) @@ -153,18 +149,14 @@ internal class QuizWaitingScreenE2eTest : QuizBaseE2eTest(QuizType.Live) { ) // Start the batch to generate a participation - runBlocking { - withTimeout(DefaultTimeoutMillis) { - startQuizExerciseBatch(getAdminAccessToken(), quiz.id, batch) - } + runBlockingWithTestTimeout { + startQuizExerciseBatch(getAdminAccessToken(), quiz.id, batch) } - val participation = runBlocking { - withTimeout(DefaultTimeoutMillis) { - participationService - .findParticipation(quiz.id, testServerUrl, accessToken) - .orThrow("Could not load participation. Expected a participation to have been created") - } + val participation = runBlockingWithTestTimeout { + participationService + .findParticipation(quiz.id, testServerUrl, accessToken) + .orThrow("Could not load participation. Expected a participation to have been created") } assertIs(participation) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 48134c21d..7aeb2024d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,8 +10,8 @@ androidxActivity = "1.8.1" androidxAppCompat = "1.7.0" androidxComposeBom = "2024.11.00" androidxLifecycle = "2.8.7" +androidGradlePlugin = "8.7.1" androidxNavigation = "2.8.4" -androidGradlePlugin = "8.7.0" androidxPaging = "3.3.4" androidxDataStore = "1.1.1" androidxPagingCompose = "3.2.1"