diff --git a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/GradesE2ETest.kt b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/GradesE2ETest.kt index 253bc5dcdf..91dda52d05 100644 --- a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/GradesE2ETest.kt +++ b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/GradesE2ETest.kt @@ -19,6 +19,7 @@ import com.instructure.dataseeding.model.SubmissionType import com.instructure.dataseeding.util.days import com.instructure.dataseeding.util.fromNow import com.instructure.dataseeding.util.iso8601 +import com.instructure.espresso.getDateInCanvasCalendarFormat import com.instructure.student.R import com.instructure.student.ui.utils.StudentTest import com.instructure.student.ui.utils.seedData @@ -67,6 +68,10 @@ class GradesE2ETest: StudentTest() { Log.d(STEP_TAG,"Assert that there is no grade for any submission yet.") courseGradesPage.assertTotalGrade(withText(R.string.noGradeText)) + Log.d(ASSERTION_TAG, "Assert that 'Base on graded assignment' checkbox is checked and the 'Show What-If Score' checkbox is NOT checked by default.") + courseGradesPage.assertBaseOnGradedAssignmentsChecked() + courseGradesPage.assertWhatIfUnChecked() + val assignmentMatcher = withText(assignment.name) val quizMatcher = withText(quiz.title) Log.d(STEP_TAG,"Refresh the page. Assert that the '${assignment.name}' assignment and '${quiz.title}' quiz are displayed and there is no grade for them.") @@ -76,8 +81,26 @@ class GradesE2ETest: StudentTest() { courseGradesPage.assertItemDisplayed(quizMatcher) courseGradesPage.assertGradeNotDisplayed(quizMatcher) + val dueDateInCanvasFormat = getDateInCanvasCalendarFormat(1.days.fromNow.iso8601) + Log.d(ASSERTION_TAG, "Assert that the '${assignment.name} assignment's due date is tomorrow ($dueDateInCanvasFormat).") + courseGradesPage.assertAssignmentDueDate(assignment.name, dueDateInCanvasFormat) + + Log.d(ASSERTION_TAG, "Assert that the '${assignment2.name} assignment's due date is tomorrow ($dueDateInCanvasFormat).") + courseGradesPage.assertAssignmentDueDate(assignment2.name, dueDateInCanvasFormat) + + Log.d(ASSERTION_TAG, "Assert that the '${quiz.title} quiz's due date has not set.") + courseGradesPage.assertAssignmentDueDate(quiz.title, "No due date") + + Log.d(ASSERTION_TAG, "Assert that all the 3 assignment's state is 'Not Submitted' yet.") + courseGradesPage.assertAssignmentStatus(assignment.name, "Not Submitted") + courseGradesPage.assertAssignmentStatus(assignment2.name, "Not Submitted") + courseGradesPage.assertAssignmentStatus(quiz.title, "Not Submitted") + Log.d(STEP_TAG,"Check in the 'What-If Score' checkbox.") - courseGradesPage.toggleWhatIf() + courseGradesPage.checkWhatIf() + + Log.d(ASSERTION_TAG, "Assert that the 'Show What-If Score' checkbox is checked.") + courseGradesPage.assertWhatIfChecked() Log.d(STEP_TAG,"Enter '12' as a what-if grade for '${assignment.name}' assignment.") courseGradesPage.enterWhatIfGrade(assignmentMatcher, "12") @@ -86,7 +109,10 @@ class GradesE2ETest: StudentTest() { courseGradesPage.assertTotalGrade(containsTextCaseInsensitive("80")) Log.d(STEP_TAG,"Check out the 'What-If Score' checkbox.") - courseGradesPage.toggleWhatIf() + courseGradesPage.uncheckWhatIf() + + Log.d(ASSERTION_TAG, "Assert that the 'Show What-If Score' checkbox is unchecked.") + courseGradesPage.assertWhatIfUnChecked() Log.d(STEP_TAG,"Assert that after disabling the 'What-If Score' checkbox there will be no 'real' grade.") courseGradesPage.assertTotalGrade(withText(R.string.noGradeText)) @@ -103,12 +129,18 @@ class GradesE2ETest: StudentTest() { assignmentMatcher, containsTextCaseInsensitive("60")) - Log.d(STEP_TAG,"Toggle 'Base on graded assignments' button. Assert that we can see the correct score (22.5%).") - courseGradesPage.toggleBaseOnGradedAssignments() + Log.d(STEP_TAG,"Uncheck 'Base on graded assignments' button.") + courseGradesPage.uncheckBaseOnGradedAssignments() + + Log.d(ASSERTION_TAG, "Assert that we can see the correct score (22.5%) and the 'Base on graded assignments' checkbox is unchecked.") + courseGradesPage.assertBaseOnGradedAssignmentsUnChecked() courseGradesPage.refreshUntilAssertTotalGrade(containsTextCaseInsensitive("22.5%")) - Log.d(STEP_TAG,"Disable 'Base on graded assignments' button. Assert that we can see the correct score (60%).") - courseGradesPage.toggleBaseOnGradedAssignments() + Log.d(STEP_TAG,"Check 'Base on graded assignments' button.") + courseGradesPage.checkBaseOnGradedAssignments() + + Log.d(ASSERTION_TAG, "Assert that we can see the correct score (60%) and the 'Base on graded assignments' checkbox is checked.") + courseGradesPage.assertBaseOnGradedAssignmentsChecked() courseGradesPage.refreshUntilAssertTotalGrade(containsTextCaseInsensitive("60")) Log.d(PREPARATION_TAG,"Seed a submission for '${assignment2.name}' assignment.") diff --git a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/compose/CalendarE2ETest.kt b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/compose/CalendarE2ETest.kt index 082a04d8ab..214f64efd2 100644 --- a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/compose/CalendarE2ETest.kt +++ b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/compose/CalendarE2ETest.kt @@ -21,7 +21,7 @@ import com.instructure.canvas.espresso.FeatureCategory import com.instructure.canvas.espresso.Priority import com.instructure.canvas.espresso.TestCategory import com.instructure.canvas.espresso.TestMetaData -import com.instructure.espresso.getCurrentDateInCanvasCalendarFormat +import com.instructure.espresso.getDateInCanvasCalendarFormat import com.instructure.pandautils.features.calendar.CalendarPrefs import com.instructure.student.ui.utils.StudentComposeTest import com.instructure.student.ui.utils.seedData @@ -74,7 +74,7 @@ class CalendarE2ETest : StudentComposeTest() { calendarEventCreateEditPage.clickSave() Log.d(STEP_TAG, "Assert that the event is displayed with the corresponding details (title, context name, date, status) on the page.") - var currentDate = getCurrentDateInCanvasCalendarFormat() + var currentDate = getDateInCanvasCalendarFormat() calendarScreenPage.assertItemDetails(newEventTitle, student.name, currentDate) Log.d(STEP_TAG, "Click on the previously created '$newEventTitle' event and assert the event details.") @@ -107,7 +107,7 @@ class CalendarE2ETest : StudentComposeTest() { calendarEventCreateEditPage.clickSave() Log.d(STEP_TAG, "Assert that the event is displayed with the corresponding modified details (title, context name, date) on the page.") - currentDate = getCurrentDateInCanvasCalendarFormat() + currentDate = getDateInCanvasCalendarFormat() calendarScreenPage.assertItemDetails(modifiedEventTitle, student.name, currentDate) Log.d(STEP_TAG, "Click on the previously created '$modifiedEventTitle' event and assert the event details.") @@ -158,7 +158,7 @@ class CalendarE2ETest : StudentComposeTest() { calendarToDoCreateUpdatePage.clickSave() Log.d(STEP_TAG, "Assert that the user has been navigated back to the Calendar Screen Page and that the previously created To Do item is displayed with the corresponding title, context and date.") - val currentDate = getCurrentDateInCanvasCalendarFormat() + val currentDate = getDateInCanvasCalendarFormat() calendarScreenPage.assertItemDetails(testTodoTitle, "To Do", "$currentDate at 12:00 PM") Log.d(STEP_TAG, "Clicks on the '$testTodoTitle' To Do item.") @@ -251,7 +251,7 @@ class CalendarE2ETest : StudentComposeTest() { calendarEventCreateEditPage.clickSave() Log.d(STEP_TAG, "Assert that the event is displayed with the corresponding details (title, context name, date, status) on the page.") - val currentDate = getCurrentDateInCanvasCalendarFormat() + val currentDate = getDateInCanvasCalendarFormat() calendarScreenPage.assertItemDetails(newEventTitle, student.name, currentDate) Log.d(STEP_TAG, "Click on the 'Add' (FAB) button and 'Add To Do' to create a new To Do.") diff --git a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/offline/OfflineGradesE2ETest.kt b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/offline/OfflineGradesE2ETest.kt index 01aaa5e5ca..fe7cd92fc9 100644 --- a/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/offline/OfflineGradesE2ETest.kt +++ b/apps/student/src/androidTest/java/com/instructure/student/ui/e2e/offline/OfflineGradesE2ETest.kt @@ -36,6 +36,7 @@ import com.instructure.dataseeding.model.SubmissionType import com.instructure.dataseeding.util.days import com.instructure.dataseeding.util.fromNow import com.instructure.dataseeding.util.iso8601 +import com.instructure.espresso.getDateInCanvasCalendarFormat import com.instructure.student.ui.e2e.offline.utils.OfflineTestUtils import com.instructure.student.ui.utils.StudentTest import com.instructure.student.ui.utils.seedData @@ -146,6 +147,23 @@ class OfflineGradesE2ETest : StudentTest() { Log.d(STEP_TAG, "Assert that the total grade is 60 because there is only one graded assignment and it's graded to 60% and we have the 'Base on graded assignments' checkbox enabled.") courseGradesPage.assertTotalGrade(containsTextCaseInsensitive("60")) + Log.d(ASSERTION_TAG, "Assert that 'Base on graded assignment' checkbox is checked and the 'Show What-If Score' checkbox is NOT checked by default.") + courseGradesPage.assertBaseOnGradedAssignmentsChecked() + courseGradesPage.assertWhatIfUnChecked() + + val dueDateInCanvasFormat = getDateInCanvasCalendarFormat(1.days.fromNow.iso8601) + Log.d(ASSERTION_TAG, "Assert that the '${assignment.name} assignment's due date is tomorrow ($dueDateInCanvasFormat).") + courseGradesPage.assertAssignmentDueDate(assignment.name, dueDateInCanvasFormat) + + Log.d(ASSERTION_TAG, "Assert that the '${assignment2.name} assignment's due date is tomorrow ($dueDateInCanvasFormat).") + courseGradesPage.assertAssignmentDueDate(assignment2.name, dueDateInCanvasFormat) + + Log.d(ASSERTION_TAG, "Assert that the '${quiz.title} quiz's due date has not set.") + courseGradesPage.assertAssignmentDueDate(quiz.title, "No due date") + + Log.d(ASSERTION_TAG, "Assert that the '${quiz.title}' quiz status is 'Not Submitted'.") + courseGradesPage.assertAssignmentStatus(quiz.title, "Not Submitted") + val assignmentMatcher = ViewMatchers.withText(assignment.name) Log.d(STEP_TAG, "Assert that the '${assignment.name}' assignment is displayed and there is 60% grade for it.") courseGradesPage.assertItemDisplayed(assignmentMatcher) @@ -162,7 +180,10 @@ class OfflineGradesE2ETest : StudentTest() { courseGradesPage.assertGradeDisplayed(assignmentMatcher2, containsTextCaseInsensitive("EX/15")) Log.d(STEP_TAG, "Check in the 'What-If Score' checkbox.") - courseGradesPage.toggleWhatIf() + courseGradesPage.checkWhatIf() + + Log.d(ASSERTION_TAG, "Assert that the 'Show What-If Score' checkbox is checked.") + courseGradesPage.assertWhatIfChecked() Log.d(STEP_TAG, "Enter '12' as a what-if grade for '${assignment.name}' assignment.") courseGradesPage.enterWhatIfGrade(assignmentMatcher, "12") @@ -176,19 +197,28 @@ class OfflineGradesE2ETest : StudentTest() { Log.d(STEP_TAG, "Assert that 'Total Grade' contains the score '64'.") courseGradesPage.assertTotalGrade(containsTextCaseInsensitive("64")) - Log.d(STEP_TAG, "Toggle 'Base on graded assignments' checkbox (while What-If Score is still enabled!). Assert that we can see the correct score (40%).") - courseGradesPage.toggleBaseOnGradedAssignments() + Log.d(STEP_TAG, "Uncheck 'Base on graded assignments' checkbox (while What-If Score is still enabled!).") + courseGradesPage.uncheckBaseOnGradedAssignments() + + Log.d(ASSERTION_TAG, "Assert that we can see the correct score (40%) and the 'Base on graded assignments' checkbox is unchecked.") + courseGradesPage.assertBaseOnGradedAssignmentsUnChecked() courseGradesPage.refreshUntilAssertTotalGrade(containsTextCaseInsensitive("40%")) - Log.d(STEP_TAG, "Check out the 'Show What-If Score' checkbox.") - courseGradesPage.toggleWhatIf() + Log.d(STEP_TAG, "Uncheck the 'Show What-If Score' checkbox.") + courseGradesPage.uncheckWhatIf() + + Log.d(ASSERTION_TAG, "Assert that the 'Show What-If Score' checkbox is unchecked.") + courseGradesPage.assertWhatIfUnChecked() Log.d(STEP_TAG, "Assert that the Total Grade is becoming 36% because there is still only one 'real' grade, but since the 'Base on graded assignments' is not checked, the score will be lower than 60% (9/30 is 36% as the 'Not Submitted' is still not counted). Also assert that the '${assignment.name}' assignment's grades has been set back to 60% as we disabled the 'Show What-If Score' checkbox.") courseGradesPage.assertTotalGrade(containsTextCaseInsensitive("36")) courseGradesPage.assertGradeDisplayed(assignmentMatcher, containsTextCaseInsensitive("60")) - Log.d(STEP_TAG, "Toggle (back) the 'Base on graded assignments' checkbox. Assert that we can see the correct score (60%).") - courseGradesPage.toggleBaseOnGradedAssignments() + Log.d(STEP_TAG, "Check 'Base on graded assignments' checkbox.") + courseGradesPage.checkBaseOnGradedAssignments() + + Log.d(ASSERTION_TAG, "Assert that we can see the correct score (60%) and the 'Base on graded assignments' checkbox is checked.") + courseGradesPage.assertBaseOnGradedAssignmentsChecked() courseGradesPage.refreshUntilAssertTotalGrade(containsTextCaseInsensitive("60%")) Log.d(STEP_TAG, "Open '${assignment.name}' assignment and assert if the Assignment Details Page is displayed with the corresponding grade." + "Navigate back to Course Grades Page.") diff --git a/apps/student/src/androidTest/java/com/instructure/student/ui/pages/CourseGradesPage.kt b/apps/student/src/androidTest/java/com/instructure/student/ui/pages/CourseGradesPage.kt index 089d2025d9..dd17e17206 100644 --- a/apps/student/src/androidTest/java/com/instructure/student/ui/pages/CourseGradesPage.kt +++ b/apps/student/src/androidTest/java/com/instructure/student/ui/pages/CourseGradesPage.kt @@ -26,8 +26,10 @@ import androidx.test.espresso.assertion.ViewAssertions import androidx.test.espresso.assertion.ViewAssertions.matches import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers.hasSibling +import androidx.test.espresso.matcher.ViewMatchers.isChecked import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast +import androidx.test.espresso.matcher.ViewMatchers.isNotChecked import androidx.test.espresso.matcher.ViewMatchers.withChild import com.instructure.canvas.espresso.containsTextCaseInsensitive import com.instructure.canvas.espresso.scrollRecyclerView @@ -38,6 +40,7 @@ import com.instructure.espresso.assertHasText import com.instructure.espresso.assertNotDisplayed import com.instructure.espresso.click import com.instructure.espresso.page.BasePage +import com.instructure.espresso.page.getStringFromResource import com.instructure.espresso.page.onView import com.instructure.espresso.page.plus import com.instructure.espresso.page.waitForView @@ -82,6 +85,17 @@ class CourseGradesPage : BasePage(R.id.courseGradesPage) { gradeValue.check(matches(matcher)) } + fun assertAssignmentDueDate(assignmentName: String, dateString: String) { + val assignmentTitleMatcher = withId(R.id.title) + withParent(R.id.textContainer) + withText(assignmentName) + withAncestor(R.id.courseGradesPage) + if(dateString != getStringFromResource(R.string.gradesNoDueDate)) onView(withId(R.id.date) + withText(dateString) + hasSibling(assignmentTitleMatcher)).assertDisplayed() + else onView(withId(R.id.date) + withText(R.string.gradesNoDueDate) + hasSibling(assignmentTitleMatcher)).assertDisplayed() + } + + fun assertAssignmentStatus(assignmentName: String, status: String) { + val assignmentTitleMatcher = withId(R.id.title) + withParent(R.id.textContainer) + withText(assignmentName) + withAncestor(R.id.courseGradesPage) + onView(withId(R.id.submissionState) + withText(status) + hasSibling(assignmentTitleMatcher)).assertDisplayed() + } + fun assertEmptyView() { onView(withId(R.id.title) + withText(R.string.noItemsToDisplayShort) + withAncestor(R.id.gradesEmptyView)).assertDisplayed() } @@ -106,14 +120,36 @@ class CourseGradesPage : BasePage(R.id.courseGradesPage) { sleep(1000) // Allow some time to react to the update. } - // TODO: Explicitly check or un-check, rather than assuming current state - fun toggleWhatIf() { - showWhatIfCheckbox.perform(click()) + fun checkWhatIf() { + showWhatIfCheckbox.check(matches(isNotChecked())).perform(click()) + } + + fun uncheckWhatIf() { + showWhatIfCheckbox.check(matches(isChecked())).perform(click()) + } + + fun assertWhatIfChecked() { + showWhatIfCheckbox.check(matches(isChecked())) + } + + fun assertWhatIfUnChecked() { + showWhatIfCheckbox.check(matches(isNotChecked())) + } + + fun checkBaseOnGradedAssignments() { + baseOnGradedAssignmentsCheckBox.check(matches(isNotChecked())).perform(click()) + } + + fun uncheckBaseOnGradedAssignments() { + baseOnGradedAssignmentsCheckBox.check(matches(isChecked())).perform(click()) + } + + fun assertBaseOnGradedAssignmentsChecked() { + baseOnGradedAssignmentsCheckBox.check(matches(isChecked())) } - // TODO: Explicitly check or un-check, rather than assuming current state - fun toggleBaseOnGradedAssignments() { - baseOnGradedAssignmentsCheckBox.perform(click()) + fun assertBaseOnGradedAssignmentsUnChecked() { + baseOnGradedAssignmentsCheckBox.check(matches(isNotChecked())) } private fun openWhatIfDialog(itemMatcher: Matcher) { diff --git a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/e2e/compose/CalendarE2ETest.kt b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/e2e/compose/CalendarE2ETest.kt index 545f379a03..fb93203730 100644 --- a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/e2e/compose/CalendarE2ETest.kt +++ b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/e2e/compose/CalendarE2ETest.kt @@ -21,7 +21,7 @@ import com.instructure.canvas.espresso.FeatureCategory import com.instructure.canvas.espresso.Priority import com.instructure.canvas.espresso.TestCategory import com.instructure.canvas.espresso.TestMetaData -import com.instructure.espresso.getCurrentDateInCanvasCalendarFormat +import com.instructure.espresso.getDateInCanvasCalendarFormat import com.instructure.pandautils.features.calendar.CalendarPrefs import com.instructure.teacher.ui.utils.TeacherComposeTest import com.instructure.teacher.ui.utils.clickCalendarTab @@ -75,7 +75,7 @@ class CalendarE2ETest: TeacherComposeTest() { calendarEventCreateEditPage.clickSave() Log.d(STEP_TAG, "Assert that the event is displayed with the corresponding details (title, context name, date, status) on the page.") - var currentDate = getCurrentDateInCanvasCalendarFormat() + var currentDate = getDateInCanvasCalendarFormat() calendarScreenPage.assertItemDetails(newEventTitle, teacher.name, currentDate) Log.d(STEP_TAG, "Click on the previously created '$newEventTitle' event and assert the event details.") @@ -108,7 +108,7 @@ class CalendarE2ETest: TeacherComposeTest() { calendarEventCreateEditPage.clickSave() Log.d(STEP_TAG, "Assert that the event is displayed with the corresponding modified details (title, context name, date) on the page.") - currentDate = getCurrentDateInCanvasCalendarFormat() + currentDate = getDateInCanvasCalendarFormat() calendarScreenPage.assertItemDetails(modifiedEventTitle, teacher.name, currentDate) Log.d(STEP_TAG, "Click on the previously created '$modifiedEventTitle' event and assert the event details.") @@ -162,7 +162,7 @@ class CalendarE2ETest: TeacherComposeTest() { calendarToDoCreateUpdatePage.clickSave() Log.d(STEP_TAG, "Assert that the user has been navigated back to the Calendar Screen Page and that the previously created To Do item is displayed with the corresponding title, context and date.") - val currentDate = getCurrentDateInCanvasCalendarFormat() + val currentDate = getDateInCanvasCalendarFormat() calendarScreenPage.assertItemDetails(testTodoTitle, "To Do", "$currentDate at 12:00 PM") Log.d(STEP_TAG, "Clicks on the '$testTodoTitle' To Do item.") @@ -255,7 +255,7 @@ class CalendarE2ETest: TeacherComposeTest() { calendarEventCreateEditPage.clickSave() Log.d(STEP_TAG, "Assert that the event is displayed with the corresponding details (title, context name, date, status) on the page.") - val currentDate = getCurrentDateInCanvasCalendarFormat() + val currentDate = getDateInCanvasCalendarFormat() calendarScreenPage.assertItemDetails(newEventTitle, teacher.name, currentDate) Log.d(STEP_TAG, "Click on the 'Add' (FAB) button and 'Add To Do' to create a new To Do.") diff --git a/automation/espresso/src/main/kotlin/com/instructure/espresso/TestingUtils.kt b/automation/espresso/src/main/kotlin/com/instructure/espresso/TestingUtils.kt index f141f60be2..3e65f0ae84 100644 --- a/automation/espresso/src/main/kotlin/com/instructure/espresso/TestingUtils.kt +++ b/automation/espresso/src/main/kotlin/com/instructure/espresso/TestingUtils.kt @@ -63,15 +63,33 @@ fun getDateInCanvasFormat(date: LocalDateTime? = null): String { } -fun getCurrentDateInCanvasCalendarFormat(): String { +fun getDateInCanvasCalendarFormat(dateString: String? = getCurrentDateInIso8601()): String { val calendar = Calendar.getInstance() + val day = calendar.get(Calendar.DAY_OF_MONTH) - var dateFormat = SimpleDateFormat("MMM dd", Locale.getDefault()) - if (day in 1..9) dateFormat = SimpleDateFormat("MMM d", Locale.getDefault()) + if(dateString != null) { + return if (day in 1..9) formatIso8601ToCustom(dateString, SimpleDateFormat("MMM d", Locale.getDefault())) + else formatIso8601ToCustom(dateString, SimpleDateFormat("MMM dd", Locale.getDefault())) + } + var dateFormat = SimpleDateFormat("MMM dd", Locale.getDefault()) + if (day in 1..9) dateFormat = SimpleDateFormat("MMM d", Locale.getDefault()) return dateFormat.format(Date()) } + +fun getCurrentDateInIso8601(): String { + val iso8601Format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.getDefault()) + return iso8601Format.format(Date()) +} + +fun formatIso8601ToCustom(iso8601DateString: String?, customDateFormat: SimpleDateFormat): String { + + val iso8601Format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.getDefault()) + val date: Date? = iso8601DateString?.let { iso8601Format.parse(it) } + + return customDateFormat.format(date!!) +} fun getCustomDateCalendar(dayDiffFromToday: Int): Calendar { val cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")) diff --git a/libs/pandautils/src/main/java/com/instructure/pandautils/features/calendarevent/createupdate/CreateUpdateEventViewModel.kt b/libs/pandautils/src/main/java/com/instructure/pandautils/features/calendarevent/createupdate/CreateUpdateEventViewModel.kt index 434d80b653..2d39e215f4 100644 --- a/libs/pandautils/src/main/java/com/instructure/pandautils/features/calendarevent/createupdate/CreateUpdateEventViewModel.kt +++ b/libs/pandautils/src/main/java/com/instructure/pandautils/features/calendarevent/createupdate/CreateUpdateEventViewModel.kt @@ -21,7 +21,7 @@ import android.content.res.Resources import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.google.ical.values.DateValueImpl +import com.google.ical.values.DateTimeValueImpl import com.google.ical.values.Frequency import com.google.ical.values.RRule import com.google.ical.values.Weekday @@ -644,7 +644,7 @@ class CreateUpdateEventViewModel @Inject constructor( } if (customFrequencyUiState.selectedDate != null) { val date = customFrequencyUiState.selectedDate - until = DateValueImpl(date.year, date.monthValue, date.dayOfMonth) + until = DateTimeValueImpl(date.year, date.monthValue, date.dayOfMonth, 0, 0, 0) } else { count = customFrequencyUiState.selectedOccurrences } diff --git a/libs/pandautils/src/test/java/com/instructure/pandautils/features/calendarevent/createupdate/CreateUpdateEventViewModelTest.kt b/libs/pandautils/src/test/java/com/instructure/pandautils/features/calendarevent/createupdate/CreateUpdateEventViewModelTest.kt index 4246555d49..4b9bda474a 100644 --- a/libs/pandautils/src/test/java/com/instructure/pandautils/features/calendarevent/createupdate/CreateUpdateEventViewModelTest.kt +++ b/libs/pandautils/src/test/java/com/instructure/pandautils/features/calendarevent/createupdate/CreateUpdateEventViewModelTest.kt @@ -536,6 +536,33 @@ class CreateUpdateEventViewModelTest { } } + @Test + fun `Frequency updates correctly - Custom with date until`() = runTest { + every { savedStateHandle.get(CreateUpdateEventFragment.INITIAL_DATE) } returns "2024-04-10" + + createViewModel() + + viewModel.handleAction(CreateUpdateEventAction.UpdateCustomFrequencyQuantity(2)) + viewModel.handleAction(CreateUpdateEventAction.UpdateCustomFrequencySelectedTimeUnitIndex(1)) + viewModel.handleAction(CreateUpdateEventAction.UpdateCustomFrequencySelectedDays(setOf(DayOfWeek.MONDAY, DayOfWeek.TUESDAY))) + viewModel.handleAction(CreateUpdateEventAction.UpdateCustomFrequencyEndDate(LocalDate.of(2024, 10, 7))) + viewModel.handleAction(CreateUpdateEventAction.SaveCustomFrequency) + viewModel.handleAction(CreateUpdateEventAction.Save(CalendarEventAPI.ModifyEventScope.ONE)) + + coVerify(exactly = 1) { + repository.createEvent( + any(), + any(), + any(), + "FREQ=WEEKLY;UNTIL=20241007T000000Z;INTERVAL=2;BYDAY=MO,TU", + any(), + any(), + any(), + any() + ) + } + } + private fun createViewModel() { viewModel = CreateUpdateEventViewModel(savedStateHandle, resources, repository, apiPrefs) }