Skip to content

Commit

Permalink
fix: course unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Sh-AhsanArif committed Jan 29, 2025
1 parent ec4a1ea commit d28d821
Show file tree
Hide file tree
Showing 4 changed files with 321 additions and 276 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import org.openedx.core.data.storage.CorePreferences
import org.openedx.core.domain.model.CourseAccessError
import org.openedx.core.domain.model.CourseDatesCalendarSync
import org.openedx.core.domain.model.CourseEnrollmentDetails
import org.openedx.core.domain.model.CourseStructure
import org.openedx.core.exception.NoCachedDataException
import org.openedx.core.extension.isFalse
import org.openedx.core.extension.isTrue
Expand All @@ -39,6 +40,7 @@ import org.openedx.core.system.notifier.RefreshDates
import org.openedx.core.system.notifier.RefreshDiscussions
import org.openedx.core.ui.Result
import org.openedx.core.ui.asResult
import org.openedx.core.ui.isLoading
import org.openedx.core.worker.CalendarSyncScheduler
import org.openedx.course.DatesShiftedSnackBar
import org.openedx.course.domain.interactor.CourseInteractor
Expand Down Expand Up @@ -175,61 +177,59 @@ class CourseContainerViewModel(
courseFlow.take(1).combine(enrollmentFlow.take(1)) { course, enrollment ->
course to enrollment
}.asResult().collect { result ->
when (result) {
is Result.Loading -> _showProgress.value = true
is Result.Success -> {
result.data.let { (_, enrollment) ->
processCourseData(enrollment)
}
_showProgress.value = result.isLoading
if (result is Result.Success) {
result.data.let { (structure, enrollment) ->
processCourseData(structure, enrollment)
}
is Result.Error -> {
_showProgress.value = false
result.exception?.let { e ->
e.printStackTrace()
if (isNetworkRelatedError(e)) {
_errorMessage.value = resourceManager.getString(CoreR.string.core_error_no_connection)
} else {
_courseAccessStatus.value = CourseAccessError.UNKNOWN
}
} ?: run {
}
if (result is Result.Error) {
result.exception?.let { e ->
e.printStackTrace()
if (isNetworkRelatedError(e)) {
_errorMessage.value =
resourceManager.getString(CoreR.string.core_error_no_connection)
} else {
_courseAccessStatus.value = CourseAccessError.UNKNOWN
}
} ?: run {
_courseAccessStatus.value = CourseAccessError.UNKNOWN
}
}
}
}
}

private suspend fun processCourseData(enrollment: CourseEnrollmentDetails) {
_courseDetails = enrollment
_showProgress.value = false
_courseDetails?.let { courseDetails ->
courseName = courseDetails.courseInfoOverview.name
loadCourseImage(courseDetails.courseInfoOverview.media?.image?.large)
if (courseDetails.hasAccess.isFalse()) {
_dataReady.value = false
if (courseDetails.isAuditAccessExpired) {
_courseAccessStatus.value =
CourseAccessError.AUDIT_EXPIRED_NOT_UPGRADABLE
} else if (courseDetails.courseInfoOverview.isStarted.not()) {
_courseAccessStatus.value = CourseAccessError.NOT_YET_STARTED
} else {
_courseAccessStatus.value = CourseAccessError.UNKNOWN
}
} else {
_courseAccessStatus.value = CourseAccessError.NONE
_isNavigationEnabled.value = true
_calendarSyncUIState.update { state ->
state.copy(isCalendarSyncEnabled = isCalendarSyncEnabled())
}
if (resumeBlockId.isNotEmpty()) {
private fun processCourseData(
courseStructure: CourseStructure,
courseDetails: CourseEnrollmentDetails
) {
_courseDetails = courseDetails
courseName = courseDetails.courseInfoOverview.name
val courseImage = courseDetails.courseInfoOverview.media?.image?.large
?: courseStructure.media?.image?.large
loadCourseImage(courseImage)
if (courseDetails.hasAccess.isFalse()) {
_dataReady.value = false
_courseAccessStatus.value = when {
courseDetails.isAuditAccessExpired -> CourseAccessError.AUDIT_EXPIRED_NOT_UPGRADABLE
courseDetails.courseInfoOverview.isStarted.not() -> CourseAccessError.NOT_YET_STARTED
else -> CourseAccessError.UNKNOWN
}
} else {
_courseAccessStatus.value = CourseAccessError.NONE
_isNavigationEnabled.value = true
_calendarSyncUIState.update { state ->
state.copy(isCalendarSyncEnabled = isCalendarSyncEnabled())
}
if (resumeBlockId.isNotEmpty()) {
// Small delay before sending block open event
viewModelScope.launch {
delay(500L)
courseNotifier.send(CourseOpenBlock(resumeBlockId))
}
_dataReady.value = true
}
} ?: run {
_courseAccessStatus.value = CourseAccessError.UNKNOWN
_dataReady.value = true
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,30 +187,34 @@ class CourseOutlineViewModel(

private fun getCourseDataInternal() {
viewModelScope.launch {
val courseStructureFlow = interactor.getCourseStructureFlow(courseId, false)
val courseStatusFlow = interactor.getCourseStatusFlow(courseId)
val courseDatesFlow = interactor.getCourseDatesFlow(courseId)
combine(
courseStructureFlow.take(1),
courseStatusFlow.take(1),
courseDatesFlow.take(1)
) { courseStructure, courseStatus, courseDatesResult ->
Triple(courseStructure, courseStatus, courseDatesResult)
}.asResult().collect {
if (it is Result.Success) {
it.data.let { (courseStructure, courseStatus, courseDatesResult) ->
val blocks = courseStructure.blockData
val datesBannerInfo = courseDatesResult.courseBanner

checkIfCalendarOutOfDate(courseDatesResult.datesSection.values.flatten())
updateOutdatedOfflineXBlocks(courseStructure)

initializeCourseData(blocks, courseStructure, courseStatus, datesBannerInfo)
try {
val courseStructureFlow = interactor.getCourseStructureFlow(courseId, false)
val courseStatusFlow = interactor.getCourseStatusFlow(courseId)
val courseDatesFlow = interactor.getCourseDatesFlow(courseId)
combine(
courseStructureFlow.take(1),
courseStatusFlow.take(1),
courseDatesFlow.take(1)
) { courseStructure, courseStatus, courseDatesResult ->
Triple(courseStructure, courseStatus, courseDatesResult)
}.asResult().collect {
if (it is Result.Success) {
it.data.let { (courseStructure, courseStatus, courseDatesResult) ->
val blocks = courseStructure.blockData
val datesBannerInfo = courseDatesResult.courseBanner

checkIfCalendarOutOfDate(courseDatesResult.datesSection.values.flatten())
updateOutdatedOfflineXBlocks(courseStructure)

initializeCourseData(blocks, courseStructure, courseStatus, datesBannerInfo)
}
}
if (it is Result.Error) {
handleCourseDataError(it.error)
}
}
if (it is Result.Error) {
handleCourseDataError(it.error)
}
} catch (e: Exception) {
handleCourseDataError(e)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.mockk.verify
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.resetMain
Expand Down Expand Up @@ -40,6 +41,8 @@ import org.openedx.core.domain.model.EnrollmentDetails
import org.openedx.core.system.connection.NetworkConnection
import org.openedx.core.system.notifier.CourseNotifier
import org.openedx.core.system.notifier.CourseStructureUpdated
import org.openedx.core.ui.Result
import org.openedx.core.ui.asResult
import org.openedx.core.worker.CalendarSyncScheduler
import org.openedx.course.domain.interactor.CourseInteractor
import org.openedx.course.presentation.CourseAnalytics
Expand Down Expand Up @@ -233,8 +236,12 @@ class CourseContainerViewModelTest {
courseRouter
)
every { networkConnection.isOnline() } returns true
coEvery { interactor.getCourseStructure(any(), any()) } throws Exception()
coEvery { interactor.getEnrollmentDetails(any()) } throws Exception()
coEvery {
interactor.getCourseStructureFlow(any(), any()).asResult()
} returns flowOf(Result.Error(Exception()))
coEvery {
interactor.getEnrollmentDetailsFlow(any()).asResult()
} returns flowOf(Result.Error(Exception()))
every {
analytics.logScreenEvent(
CourseAnalyticsEvent.DASHBOARD.eventName,
Expand All @@ -250,7 +257,7 @@ class CourseContainerViewModelTest {
viewModel.fetchCourseDetails()
advanceUntilIdle()

coVerify(exactly = 1) { interactor.getEnrollmentDetails(any()) }
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any()) }
verify(exactly = 1) {
analytics.logScreenEvent(
CourseAnalyticsEvent.DASHBOARD.eventName,
Expand Down Expand Up @@ -285,8 +292,8 @@ class CourseContainerViewModelTest {
courseRouter
)
every { networkConnection.isOnline() } returns true
coEvery { interactor.getCourseStructure(any(), any()) } returns courseStructure
coEvery { interactor.getEnrollmentDetails(any()) } returns enrollmentDetails
coEvery { interactor.getCourseStructureFlow(any(), any()) } returns flowOf(courseStructure)
coEvery { interactor.getEnrollmentDetailsFlow(any()) } returns flowOf(enrollmentDetails)
every {
analytics.logScreenEvent(
CourseAnalyticsEvent.DASHBOARD.eventName,
Expand All @@ -302,7 +309,7 @@ class CourseContainerViewModelTest {
viewModel.fetchCourseDetails()
advanceUntilIdle()

coVerify(exactly = 1) { interactor.getEnrollmentDetails(any()) }
coVerify(exactly = 1) { interactor.getEnrollmentDetailsFlow(any()) }
verify(exactly = 1) {
analytics.logScreenEvent(
CourseAnalyticsEvent.DASHBOARD.eventName,
Expand Down Expand Up @@ -338,7 +345,8 @@ class CourseContainerViewModelTest {
courseRouter
)
every { networkConnection.isOnline() } returns false
coEvery { interactor.getEnrollmentDetails(any()) } returns enrollmentDetails
coEvery { interactor.getCourseStructureFlow(any(), any()) } returns flowOf(courseStructure)
coEvery { interactor.getEnrollmentDetailsFlow(any()) } returns flowOf(enrollmentDetails)
every {
analytics.logScreenEvent(
CourseAnalyticsEvent.DASHBOARD.eventName,
Expand Down
Loading

0 comments on commit d28d821

Please sign in to comment.