Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,14 @@ class ParentInboxCoursePickerViewModel @Inject constructor(
return@launch
}

val studentContextItems = enrollments.mapNotNull { enrollment ->
val course = courses.find { it.id == enrollment.courseId } ?: return@mapNotNull null
val user = enrollment.observedUser ?: return@mapNotNull null
StudentContextItem(course, user)
}
val studentContextItems = enrollments
.filter { it.enrollmentState in listOf("active", "invited", "creation_pending") }
.mapNotNull { enrollment ->
val course = courses.find { it.id == enrollment.courseId } ?: return@mapNotNull null
val user = enrollment.observedUser ?: return@mapNotNull null
StudentContextItem(course, user)
}
.filter { !it.course.isPastEnrolment() }

_uiState.update { it.copy(screenState = ScreenState.Content, studentContextItems = studentContextItems.distinct()) }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,10 @@ class ParentInboxCoursePickerViewModelTest {
fun `loadCoursePickerItems should update uiState with data when enrollments and courses are successful`() {
val courses = listOf(Course(1, "Course 1"), Course(2, "Course 2"))
val users = listOf(User(1, "User 1"), User(2, "User 2"))
val enrollments = listOf(Enrollment(1, courseId = 1, observedUser = users[0]), Enrollment(2, courseId = 2, observedUser = users[1]))
val enrollments = listOf(
Enrollment(1, courseId = 1, enrollmentState = "active", observedUser = users[0]),
Enrollment(2, courseId = 2, enrollmentState = "active", observedUser = users[1])
)
coEvery { repository.getCourses() } returns DataResult.Success(courses)
coEvery { repository.getEnrollments() } returns DataResult.Success(enrollments)

Expand All @@ -112,6 +115,123 @@ class ParentInboxCoursePickerViewModelTest {
assertEquals(users[1], viewModel.uiState.value.studentContextItems[1].user)
}

@Test
fun `loadCoursePickerItems should filter out completed and inactive enrollments`() {
val courses = listOf(
Course(1, "Active Course"),
Course(2, "Completed Course"),
Course(3, "Inactive Course")
)
val users = listOf(User(1, "User 1"), User(2, "User 2"), User(3, "User 3"))
val enrollments = listOf(
Enrollment(1, courseId = 1, enrollmentState = "active", observedUser = users[0]),
Enrollment(2, courseId = 2, enrollmentState = "completed", observedUser = users[1]),
Enrollment(3, courseId = 3, enrollmentState = "inactive", observedUser = users[2])
)
coEvery { repository.getCourses() } returns DataResult.Success(courses)
coEvery { repository.getEnrollments() } returns DataResult.Success(enrollments)

val viewModel = getViewModel()
assertEquals(ScreenState.Content, viewModel.uiState.value.screenState)
assertEquals(1, viewModel.uiState.value.studentContextItems.size)
assertEquals(courses[0], viewModel.uiState.value.studentContextItems[0].course)
assertEquals(users[0], viewModel.uiState.value.studentContextItems[0].user)
}

@Test
fun `loadCoursePickerItems should include active, invited, and creation_pending enrollments`() {
val courses = listOf(
Course(1, "Active Course"),
Course(2, "Invited Course"),
Course(3, "Creation Pending Course")
)
val users = listOf(User(1, "User 1"), User(2, "User 2"), User(3, "User 3"))
val enrollments = listOf(
Enrollment(1, courseId = 1, enrollmentState = "active", observedUser = users[0]),
Enrollment(2, courseId = 2, enrollmentState = "invited", observedUser = users[1]),
Enrollment(3, courseId = 3, enrollmentState = "creation_pending", observedUser = users[2])
)
coEvery { repository.getCourses() } returns DataResult.Success(courses)
coEvery { repository.getEnrollments() } returns DataResult.Success(enrollments)

val viewModel = getViewModel()
assertEquals(ScreenState.Content, viewModel.uiState.value.screenState)
assertEquals(3, viewModel.uiState.value.studentContextItems.size)
assertEquals(courses[0], viewModel.uiState.value.studentContextItems[0].course)
assertEquals(users[0], viewModel.uiState.value.studentContextItems[0].user)
assertEquals(courses[1], viewModel.uiState.value.studentContextItems[1].course)
assertEquals(users[1], viewModel.uiState.value.studentContextItems[1].user)
assertEquals(courses[2], viewModel.uiState.value.studentContextItems[2].course)
assertEquals(users[2], viewModel.uiState.value.studentContextItems[2].user)
}

@Test
fun `loadCoursePickerItems should filter out soft concluded courses with past term dates`() {
val pastTermEndDate = "2024-01-01T00:00:00Z"
val futureTermEndDate = "2026-12-31T23:59:59Z"
val courses = listOf(
Course(1, "Current Course", term = com.instructure.canvasapi2.models.Term(endAt = futureTermEndDate)),
Course(2, "Soft Concluded Course", term = com.instructure.canvasapi2.models.Term(endAt = pastTermEndDate))
)
val users = listOf(User(1, "User 1"), User(2, "User 2"))
val enrollments = listOf(
Enrollment(1, courseId = 1, enrollmentState = "active", observedUser = users[0]),
Enrollment(2, courseId = 2, enrollmentState = "active", observedUser = users[1])
)
coEvery { repository.getCourses() } returns DataResult.Success(courses)
coEvery { repository.getEnrollments() } returns DataResult.Success(enrollments)

val viewModel = getViewModel()
assertEquals(ScreenState.Content, viewModel.uiState.value.screenState)
assertEquals(1, viewModel.uiState.value.studentContextItems.size)
assertEquals(courses[0], viewModel.uiState.value.studentContextItems[0].course)
assertEquals(users[0], viewModel.uiState.value.studentContextItems[0].user)
}

@Test
fun `loadCoursePickerItems should filter out soft concluded courses with past course end dates`() {
val pastCourseEndDate = "2024-01-01T00:00:00Z"
val futureCourseEndDate = "2026-12-31T23:59:59Z"
val courses = listOf(
Course(1, "Current Course", endAt = futureCourseEndDate, restrictEnrollmentsToCourseDate = true),
Course(2, "Soft Concluded Course", endAt = pastCourseEndDate, restrictEnrollmentsToCourseDate = true)
)
val users = listOf(User(1, "User 1"), User(2, "User 2"))
val enrollments = listOf(
Enrollment(1, courseId = 1, enrollmentState = "active", observedUser = users[0]),
Enrollment(2, courseId = 2, enrollmentState = "active", observedUser = users[1])
)
coEvery { repository.getCourses() } returns DataResult.Success(courses)
coEvery { repository.getEnrollments() } returns DataResult.Success(enrollments)

val viewModel = getViewModel()
assertEquals(ScreenState.Content, viewModel.uiState.value.screenState)
assertEquals(1, viewModel.uiState.value.studentContextItems.size)
assertEquals(courses[0], viewModel.uiState.value.studentContextItems[0].course)
assertEquals(users[0], viewModel.uiState.value.studentContextItems[0].user)
}

@Test
fun `loadCoursePickerItems should filter out hard concluded courses with completed workflow state`() {
val courses = listOf(
Course(1, "Active Course", workflowState = Course.WorkflowState.AVAILABLE),
Course(2, "Hard Concluded Course", workflowState = Course.WorkflowState.COMPLETED)
)
val users = listOf(User(1, "User 1"), User(2, "User 2"))
val enrollments = listOf(
Enrollment(1, courseId = 1, enrollmentState = "active", observedUser = users[0]),
Enrollment(2, courseId = 2, enrollmentState = "active", observedUser = users[1])
)
coEvery { repository.getCourses() } returns DataResult.Success(courses)
coEvery { repository.getEnrollments() } returns DataResult.Success(enrollments)

val viewModel = getViewModel()
assertEquals(ScreenState.Content, viewModel.uiState.value.screenState)
assertEquals(1, viewModel.uiState.value.studentContextItems.size)
assertEquals(courses[0], viewModel.uiState.value.studentContextItems[0].course)
assertEquals(users[0], viewModel.uiState.value.studentContextItems[0].user)
}

private fun getViewModel(): ParentInboxCoursePickerViewModel {
return ParentInboxCoursePickerViewModel(context, repository, apiPrefs)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ object CourseAPI {
@GET("courses?state[]=completed&state[]=available&state[]=unpublished")
fun getCoursesByEnrollmentType(@Query("enrollment_type") type: String): Call<List<Course>>

@GET("courses?state[]=completed&state[]=available")
@GET("courses?state[]=completed&state[]=available&include[]=term")
suspend fun getCoursesByEnrollmentType(@Query("enrollment_type") type: String, @Tag params: RestParams): DataResult<List<Course>>

// TODO: Set up pagination when API is fixed and remove per_page query parameterø
Expand Down
Loading