Skip to content

Commit d28d821

Browse files
author
Ahsan Arif
committed
fix: course unit tests
1 parent ec4a1ea commit d28d821

File tree

4 files changed

+321
-276
lines changed

4 files changed

+321
-276
lines changed

course/src/main/java/org/openedx/course/presentation/container/CourseContainerViewModel.kt

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import org.openedx.core.data.storage.CorePreferences
2222
import org.openedx.core.domain.model.CourseAccessError
2323
import org.openedx.core.domain.model.CourseDatesCalendarSync
2424
import org.openedx.core.domain.model.CourseEnrollmentDetails
25+
import org.openedx.core.domain.model.CourseStructure
2526
import org.openedx.core.exception.NoCachedDataException
2627
import org.openedx.core.extension.isFalse
2728
import org.openedx.core.extension.isTrue
@@ -39,6 +40,7 @@ import org.openedx.core.system.notifier.RefreshDates
3940
import org.openedx.core.system.notifier.RefreshDiscussions
4041
import org.openedx.core.ui.Result
4142
import org.openedx.core.ui.asResult
43+
import org.openedx.core.ui.isLoading
4244
import org.openedx.core.worker.CalendarSyncScheduler
4345
import org.openedx.course.DatesShiftedSnackBar
4446
import org.openedx.course.domain.interactor.CourseInteractor
@@ -175,61 +177,59 @@ class CourseContainerViewModel(
175177
courseFlow.take(1).combine(enrollmentFlow.take(1)) { course, enrollment ->
176178
course to enrollment
177179
}.asResult().collect { result ->
178-
when (result) {
179-
is Result.Loading -> _showProgress.value = true
180-
is Result.Success -> {
181-
result.data.let { (_, enrollment) ->
182-
processCourseData(enrollment)
183-
}
180+
_showProgress.value = result.isLoading
181+
if (result is Result.Success) {
182+
result.data.let { (structure, enrollment) ->
183+
processCourseData(structure, enrollment)
184184
}
185-
is Result.Error -> {
186-
_showProgress.value = false
187-
result.exception?.let { e ->
188-
e.printStackTrace()
189-
if (isNetworkRelatedError(e)) {
190-
_errorMessage.value = resourceManager.getString(CoreR.string.core_error_no_connection)
191-
} else {
192-
_courseAccessStatus.value = CourseAccessError.UNKNOWN
193-
}
194-
} ?: run {
185+
}
186+
if (result is Result.Error) {
187+
result.exception?.let { e ->
188+
e.printStackTrace()
189+
if (isNetworkRelatedError(e)) {
190+
_errorMessage.value =
191+
resourceManager.getString(CoreR.string.core_error_no_connection)
192+
} else {
195193
_courseAccessStatus.value = CourseAccessError.UNKNOWN
196194
}
195+
} ?: run {
196+
_courseAccessStatus.value = CourseAccessError.UNKNOWN
197197
}
198198
}
199199
}
200200
}
201201
}
202202

203-
private suspend fun processCourseData(enrollment: CourseEnrollmentDetails) {
204-
_courseDetails = enrollment
205-
_showProgress.value = false
206-
_courseDetails?.let { courseDetails ->
207-
courseName = courseDetails.courseInfoOverview.name
208-
loadCourseImage(courseDetails.courseInfoOverview.media?.image?.large)
209-
if (courseDetails.hasAccess.isFalse()) {
210-
_dataReady.value = false
211-
if (courseDetails.isAuditAccessExpired) {
212-
_courseAccessStatus.value =
213-
CourseAccessError.AUDIT_EXPIRED_NOT_UPGRADABLE
214-
} else if (courseDetails.courseInfoOverview.isStarted.not()) {
215-
_courseAccessStatus.value = CourseAccessError.NOT_YET_STARTED
216-
} else {
217-
_courseAccessStatus.value = CourseAccessError.UNKNOWN
218-
}
219-
} else {
220-
_courseAccessStatus.value = CourseAccessError.NONE
221-
_isNavigationEnabled.value = true
222-
_calendarSyncUIState.update { state ->
223-
state.copy(isCalendarSyncEnabled = isCalendarSyncEnabled())
224-
}
225-
if (resumeBlockId.isNotEmpty()) {
203+
private fun processCourseData(
204+
courseStructure: CourseStructure,
205+
courseDetails: CourseEnrollmentDetails
206+
) {
207+
_courseDetails = courseDetails
208+
courseName = courseDetails.courseInfoOverview.name
209+
val courseImage = courseDetails.courseInfoOverview.media?.image?.large
210+
?: courseStructure.media?.image?.large
211+
loadCourseImage(courseImage)
212+
if (courseDetails.hasAccess.isFalse()) {
213+
_dataReady.value = false
214+
_courseAccessStatus.value = when {
215+
courseDetails.isAuditAccessExpired -> CourseAccessError.AUDIT_EXPIRED_NOT_UPGRADABLE
216+
courseDetails.courseInfoOverview.isStarted.not() -> CourseAccessError.NOT_YET_STARTED
217+
else -> CourseAccessError.UNKNOWN
218+
}
219+
} else {
220+
_courseAccessStatus.value = CourseAccessError.NONE
221+
_isNavigationEnabled.value = true
222+
_calendarSyncUIState.update { state ->
223+
state.copy(isCalendarSyncEnabled = isCalendarSyncEnabled())
224+
}
225+
if (resumeBlockId.isNotEmpty()) {
226+
// Small delay before sending block open event
227+
viewModelScope.launch {
226228
delay(500L)
227229
courseNotifier.send(CourseOpenBlock(resumeBlockId))
228230
}
229-
_dataReady.value = true
230231
}
231-
} ?: run {
232-
_courseAccessStatus.value = CourseAccessError.UNKNOWN
232+
_dataReady.value = true
233233
}
234234
}
235235

course/src/main/java/org/openedx/course/presentation/outline/CourseOutlineViewModel.kt

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -187,30 +187,34 @@ class CourseOutlineViewModel(
187187

188188
private fun getCourseDataInternal() {
189189
viewModelScope.launch {
190-
val courseStructureFlow = interactor.getCourseStructureFlow(courseId, false)
191-
val courseStatusFlow = interactor.getCourseStatusFlow(courseId)
192-
val courseDatesFlow = interactor.getCourseDatesFlow(courseId)
193-
combine(
194-
courseStructureFlow.take(1),
195-
courseStatusFlow.take(1),
196-
courseDatesFlow.take(1)
197-
) { courseStructure, courseStatus, courseDatesResult ->
198-
Triple(courseStructure, courseStatus, courseDatesResult)
199-
}.asResult().collect {
200-
if (it is Result.Success) {
201-
it.data.let { (courseStructure, courseStatus, courseDatesResult) ->
202-
val blocks = courseStructure.blockData
203-
val datesBannerInfo = courseDatesResult.courseBanner
204-
205-
checkIfCalendarOutOfDate(courseDatesResult.datesSection.values.flatten())
206-
updateOutdatedOfflineXBlocks(courseStructure)
207-
208-
initializeCourseData(blocks, courseStructure, courseStatus, datesBannerInfo)
190+
try {
191+
val courseStructureFlow = interactor.getCourseStructureFlow(courseId, false)
192+
val courseStatusFlow = interactor.getCourseStatusFlow(courseId)
193+
val courseDatesFlow = interactor.getCourseDatesFlow(courseId)
194+
combine(
195+
courseStructureFlow.take(1),
196+
courseStatusFlow.take(1),
197+
courseDatesFlow.take(1)
198+
) { courseStructure, courseStatus, courseDatesResult ->
199+
Triple(courseStructure, courseStatus, courseDatesResult)
200+
}.asResult().collect {
201+
if (it is Result.Success) {
202+
it.data.let { (courseStructure, courseStatus, courseDatesResult) ->
203+
val blocks = courseStructure.blockData
204+
val datesBannerInfo = courseDatesResult.courseBanner
205+
206+
checkIfCalendarOutOfDate(courseDatesResult.datesSection.values.flatten())
207+
updateOutdatedOfflineXBlocks(courseStructure)
208+
209+
initializeCourseData(blocks, courseStructure, courseStatus, datesBannerInfo)
210+
}
211+
}
212+
if (it is Result.Error) {
213+
handleCourseDataError(it.error)
209214
}
210215
}
211-
if (it is Result.Error) {
212-
handleCourseDataError(it.error)
213-
}
216+
} catch (e: Exception) {
217+
handleCourseDataError(e)
214218
}
215219
}
216220
}

course/src/test/java/org/openedx/course/presentation/container/CourseContainerViewModelTest.kt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import io.mockk.verify
1111
import kotlinx.coroutines.Dispatchers
1212
import kotlinx.coroutines.ExperimentalCoroutinesApi
1313
import kotlinx.coroutines.flow.emptyFlow
14+
import kotlinx.coroutines.flow.flowOf
1415
import kotlinx.coroutines.test.StandardTestDispatcher
1516
import kotlinx.coroutines.test.advanceUntilIdle
1617
import kotlinx.coroutines.test.resetMain
@@ -40,6 +41,8 @@ import org.openedx.core.domain.model.EnrollmentDetails
4041
import org.openedx.core.system.connection.NetworkConnection
4142
import org.openedx.core.system.notifier.CourseNotifier
4243
import org.openedx.core.system.notifier.CourseStructureUpdated
44+
import org.openedx.core.ui.Result
45+
import org.openedx.core.ui.asResult
4346
import org.openedx.core.worker.CalendarSyncScheduler
4447
import org.openedx.course.domain.interactor.CourseInteractor
4548
import org.openedx.course.presentation.CourseAnalytics
@@ -233,8 +236,12 @@ class CourseContainerViewModelTest {
233236
courseRouter
234237
)
235238
every { networkConnection.isOnline() } returns true
236-
coEvery { interactor.getCourseStructure(any(), any()) } throws Exception()
237-
coEvery { interactor.getEnrollmentDetails(any()) } throws Exception()
239+
coEvery {
240+
interactor.getCourseStructureFlow(any(), any()).asResult()
241+
} returns flowOf(Result.Error(Exception()))
242+
coEvery {
243+
interactor.getEnrollmentDetailsFlow(any()).asResult()
244+
} returns flowOf(Result.Error(Exception()))
238245
every {
239246
analytics.logScreenEvent(
240247
CourseAnalyticsEvent.DASHBOARD.eventName,
@@ -250,7 +257,7 @@ class CourseContainerViewModelTest {
250257
viewModel.fetchCourseDetails()
251258
advanceUntilIdle()
252259

253-
coVerify(exactly = 1) { interactor.getEnrollmentDetails(any()) }
260+
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any()) }
254261
verify(exactly = 1) {
255262
analytics.logScreenEvent(
256263
CourseAnalyticsEvent.DASHBOARD.eventName,
@@ -285,8 +292,8 @@ class CourseContainerViewModelTest {
285292
courseRouter
286293
)
287294
every { networkConnection.isOnline() } returns true
288-
coEvery { interactor.getCourseStructure(any(), any()) } returns courseStructure
289-
coEvery { interactor.getEnrollmentDetails(any()) } returns enrollmentDetails
295+
coEvery { interactor.getCourseStructureFlow(any(), any()) } returns flowOf(courseStructure)
296+
coEvery { interactor.getEnrollmentDetailsFlow(any()) } returns flowOf(enrollmentDetails)
290297
every {
291298
analytics.logScreenEvent(
292299
CourseAnalyticsEvent.DASHBOARD.eventName,
@@ -302,7 +309,7 @@ class CourseContainerViewModelTest {
302309
viewModel.fetchCourseDetails()
303310
advanceUntilIdle()
304311

305-
coVerify(exactly = 1) { interactor.getEnrollmentDetails(any()) }
312+
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any()) }
306313
verify(exactly = 1) {
307314
analytics.logScreenEvent(
308315
CourseAnalyticsEvent.DASHBOARD.eventName,
@@ -338,7 +345,8 @@ class CourseContainerViewModelTest {
338345
courseRouter
339346
)
340347
every { networkConnection.isOnline() } returns false
341-
coEvery { interactor.getEnrollmentDetails(any()) } returns enrollmentDetails
348+
coEvery { interactor.getCourseStructureFlow(any(), any()) } returns flowOf(courseStructure)
349+
coEvery { interactor.getEnrollmentDetailsFlow(any()) } returns flowOf(enrollmentDetails)
342350
every {
343351
analytics.logScreenEvent(
344352
CourseAnalyticsEvent.DASHBOARD.eventName,

0 commit comments

Comments
 (0)