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 @@ -70,10 +70,6 @@ fun SpeedGraderScreen(
val scope = rememberCoroutineScope()
val snackbarHostState = remember { SnackbarHostState() }

val pagerState = rememberPagerState(
pageCount = { uiState.submissionIds.size },
initialPage = uiState.selectedItem
)
val viewPagerEnabled by sharedViewModel.viewPagerEnabled.collectAsState(initial = true)

val errorEvent by sharedViewModel.errorState.collectAsState(initial = null)
Expand Down Expand Up @@ -151,6 +147,11 @@ fun SpeedGraderScreen(
}

else -> {
val pagerState = rememberPagerState(
pageCount = { uiState.submissionIds.size },
initialPage = uiState.selectedItem
)

HorizontalPager(
modifier = Modifier.padding(padding),
state = pagerState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class SpeedGraderViewModel @Inject constructor(

private val selectedItem: Int = savedStateHandle[Const.SELECTED_ITEM] ?: 0

private val submissionId: Long? = savedStateHandle[Const.SUBMISSION_ID]

private var assignment: Assignment? = null

private val _uiState = MutableStateFlow(
Expand Down Expand Up @@ -90,22 +92,29 @@ class SpeedGraderViewModel @Inject constructor(
courseId = courseId,
forceNetwork = false
)
val ids = if (submissionIds.isEmpty()) {
assignmentSubmissionRepository.getGradeableStudentSubmissions(
val ids: List<Long>
val selectedItem: Int
if (submissionIds.isEmpty()) {
val submissions = assignmentSubmissionRepository.getGradeableStudentSubmissions(
assignmentId,
courseId,
false
).map { it.id }
)
val submissionIndex = submissions.indexOfFirst { it.submission?.id == submissionId }
selectedItem = if (submissionIndex == -1) 0 else submissionIndex
ids = submissions.map { it.id }
} else {
submissionIds.toList()
ids = submissionIds.toList()
selectedItem = _uiState.value.selectedItem
}
val assignmentDetails = repository.getAssignmentDetails(assignmentId)
_uiState.update {
it.copy(
assignmentName = assignmentDetails.assignment?.title.orEmpty(),
courseName = assignmentDetails.assignment?.course?.name.orEmpty(),
loading = false,
submissionIds = ids
submissionIds = ids,
selectedItem = selectedItem
)
}
} catch (e: Exception) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,4 +198,147 @@ class SpeedGraderViewModelTest {
errorHandler.postError("Error", any())
}
}

@Test
fun `fetchData uses submissionIds when provided`() = runTest {
val course = AssignmentDetailsQuery.Course(name = "Test Course", _id = "1")
val assignment = AssignmentDetailsQuery.Assignment(title = "Test Assignment", course = course)
val assignmentDetails = AssignmentDetailsQuery.Data(assignment = assignment)
coEvery { repository.getAssignmentDetails(1L) } returns assignmentDetails

savedStateHandle = SavedStateHandle(
mapOf(
Const.COURSE_ID to 1L,
Const.ASSIGNMENT_ID to 1L,
SpeedGraderFragment.FILTERED_SUBMISSION_IDS to longArrayOf(10L, 20L, 30L),
Const.SELECTED_ITEM to 1
)
)

createViewModel()
testDispatcher.scheduler.advanceUntilIdle()

val uiState = viewModel.uiState.first()
assertEquals(listOf(10L, 20L, 30L), uiState.submissionIds)
assertEquals(1, uiState.selectedItem)
coVerify(exactly = 0) { assignmentSubmissionRepository.getGradeableStudentSubmissions(any<Long>(), any(), any()) }
}

@Test
fun `fetchData loads all submissions when submissionIds empty and sets selectedItem to 0 when submissionId not found`() = runTest {
val course = AssignmentDetailsQuery.Course(name = "Test Course", _id = "1")
val assignment = AssignmentDetailsQuery.Assignment(title = "Test Assignment", course = course)
val assignmentDetails = AssignmentDetailsQuery.Data(assignment = assignment)
coEvery { repository.getAssignmentDetails(1L) } returns assignmentDetails

val mockSubmissions = listOf(
mockk<com.instructure.canvasapi2.models.GradeableStudentSubmission>(relaxed = true).apply {
coEvery { id } returns 100L
coEvery { submission?.id } returns 1000L
},
mockk<com.instructure.canvasapi2.models.GradeableStudentSubmission>(relaxed = true).apply {
coEvery { id } returns 200L
coEvery { submission?.id } returns 2000L
},
mockk<com.instructure.canvasapi2.models.GradeableStudentSubmission>(relaxed = true).apply {
coEvery { id } returns 300L
coEvery { submission?.id } returns 3000L
}
)
coEvery { assignmentSubmissionRepository.getGradeableStudentSubmissions(1L, 1L, false) } returns mockSubmissions

savedStateHandle = SavedStateHandle(
mapOf(
Const.COURSE_ID to 1L,
Const.ASSIGNMENT_ID to 1L,
SpeedGraderFragment.FILTERED_SUBMISSION_IDS to longArrayOf(),
Const.SUBMISSION_ID to 9999L
)
)

createViewModel()
testDispatcher.scheduler.advanceUntilIdle()

val uiState = viewModel.uiState.first()
assertEquals(listOf(100L, 200L, 300L), uiState.submissionIds)
assertEquals(0, uiState.selectedItem)
coVerify(exactly = 1) { assignmentSubmissionRepository.getGradeableStudentSubmissions(1L, 1L, false) }
}

@Test
fun `fetchData loads all submissions when submissionIds empty and sets selectedItem based on submissionId`() = runTest {
val course = AssignmentDetailsQuery.Course(name = "Test Course", _id = "1")
val assignment = AssignmentDetailsQuery.Assignment(title = "Test Assignment", course = course)
val assignmentDetails = AssignmentDetailsQuery.Data(assignment = assignment)
coEvery { repository.getAssignmentDetails(1L) } returns assignmentDetails

val mockSubmissions = listOf(
mockk<com.instructure.canvasapi2.models.GradeableStudentSubmission>(relaxed = true).apply {
coEvery { id } returns 100L
coEvery { submission?.id } returns 1000L
},
mockk<com.instructure.canvasapi2.models.GradeableStudentSubmission>(relaxed = true).apply {
coEvery { id } returns 200L
coEvery { submission?.id } returns 2000L
},
mockk<com.instructure.canvasapi2.models.GradeableStudentSubmission>(relaxed = true).apply {
coEvery { id } returns 300L
coEvery { submission?.id } returns 3000L
}
)
coEvery { assignmentSubmissionRepository.getGradeableStudentSubmissions(1L, 1L, false) } returns mockSubmissions

savedStateHandle = SavedStateHandle(
mapOf(
Const.COURSE_ID to 1L,
Const.ASSIGNMENT_ID to 1L,
SpeedGraderFragment.FILTERED_SUBMISSION_IDS to longArrayOf(),
Const.SUBMISSION_ID to 2000L
)
)

createViewModel()
testDispatcher.scheduler.advanceUntilIdle()

val uiState = viewModel.uiState.first()
assertEquals(listOf(100L, 200L, 300L), uiState.submissionIds)
assertEquals(1, uiState.selectedItem)
coVerify(exactly = 1) { assignmentSubmissionRepository.getGradeableStudentSubmissions(1L, 1L, false) }
}

@Test
fun `fetchData loads all submissions when submissionIds empty without submissionId parameter`() = runTest {
val course = AssignmentDetailsQuery.Course(name = "Test Course", _id = "1")
val assignment = AssignmentDetailsQuery.Assignment(title = "Test Assignment", course = course)
val assignmentDetails = AssignmentDetailsQuery.Data(assignment = assignment)
coEvery { repository.getAssignmentDetails(1L) } returns assignmentDetails

val mockSubmissions = listOf(
mockk<com.instructure.canvasapi2.models.GradeableStudentSubmission>(relaxed = true).apply {
coEvery { id } returns 100L
coEvery { submission?.id } returns 1000L
},
mockk<com.instructure.canvasapi2.models.GradeableStudentSubmission>(relaxed = true).apply {
coEvery { id } returns 200L
coEvery { submission?.id } returns 2000L
}
)
coEvery { assignmentSubmissionRepository.getGradeableStudentSubmissions(1L, 1L, false) } returns mockSubmissions

savedStateHandle = SavedStateHandle(
mapOf(
Const.COURSE_ID to 1L,
Const.ASSIGNMENT_ID to 1L,
SpeedGraderFragment.FILTERED_SUBMISSION_IDS to longArrayOf()
)
)

createViewModel()
testDispatcher.scheduler.advanceUntilIdle()

val uiState = viewModel.uiState.first()
assertEquals(listOf(100L, 200L), uiState.submissionIds)
assertEquals(0, uiState.selectedItem)
coVerify(exactly = 1) { assignmentSubmissionRepository.getGradeableStudentSubmissions(1L, 1L, false) }
}
}
Loading