Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MBL-18013][Student][Parent] Refactor reminder logic #2628

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8fcdc29
Implement datetime picker
domonkosadam Nov 5, 2024
00596af
Migrate date selection to flow
domonkosadam Nov 5, 2024
54dff2d
Fix string resources
domonkosadam Nov 5, 2024
0193a7c
Refactor reminder behavior
domonkosadam Nov 6, 2024
ce9a4ab
Fix calendar handling
domonkosadam Nov 6, 2024
ec5027b
Refactor to callback flows, fix tests
domonkosadam Nov 6, 2024
d6f6299
Fix tests
domonkosadam Nov 7, 2024
38e0d54
Fix parent tests
domonkosadam Nov 7, 2024
0dbb014
Fix tests
domonkosadam Nov 7, 2024
78dbe52
Refactor dialog flow handling
domonkosadam Nov 13, 2024
52997d1
Reminder dialog logic
domonkosadam Nov 13, 2024
e6cea8e
Sort reminders
domonkosadam Nov 13, 2024
897239a
Fix before due date reminders
domonkosadam Nov 13, 2024
5b90a4f
Implement new reminder design
domonkosadam Nov 15, 2024
6f5e688
Merge branch 'master' into MBL-18013-Refactor-reminder-logic
domonkosadam Nov 15, 2024
e42cb2e
Fix notification handling
domonkosadam Nov 15, 2024
1e6a51f
Fix test
domonkosadam Nov 15, 2024
836cfd4
Fix tests
domonkosadam Nov 18, 2024
5678ade
Merge branch 'master' into MBL-18013-Refactor-reminder-logic
domonkosadam Nov 18, 2024
888ae60
Fix errors
domonkosadam Nov 18, 2024
f6c050f
Fix reminder visibility
domonkosadam Nov 18, 2024
268e0c2
UI fixes
domonkosadam Nov 19, 2024
bc23496
Fix findings
domonkosadam Nov 19, 2024
86ebebd
Merge branch 'master' into MBL-18013-Refactor-reminder-logic
domonkosadam Nov 19, 2024
a28c20d
Fix tests
domonkosadam Nov 19, 2024
1f038ca
Fix accessibility check in tests
domonkosadam Nov 19, 2024
fb49106
Fix accessibility in tests
domonkosadam Nov 19, 2024
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 @@ -19,8 +19,13 @@ import androidx.compose.ui.platform.ComposeView
import androidx.test.espresso.matcher.ViewMatchers
import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils
import com.google.android.apps.common.testing.accessibility.framework.checks.SpeakableTextPresentCheck
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.canvas.espresso.checkToastText
import com.instructure.canvas.espresso.common.pages.AssignmentDetailsPage
import com.instructure.canvas.espresso.common.pages.ReminderPage
import com.instructure.canvas.espresso.mockCanvas.MockCanvas
import com.instructure.canvas.espresso.mockCanvas.addAssignment
import com.instructure.canvas.espresso.mockCanvas.addAssignmentsToGroups
Expand All @@ -33,6 +38,7 @@ import com.instructure.canvasapi2.models.Assignment
import com.instructure.canvasapi2.models.CourseSettings
import com.instructure.canvasapi2.utils.toApiString
import com.instructure.espresso.ModuleItemInteractions
import com.instructure.pandautils.utils.toFormattedString
import com.instructure.parentapp.R
import com.instructure.parentapp.utils.ParentComposeTest
import com.instructure.parentapp.utils.tokenLogin
Expand All @@ -47,6 +53,7 @@ class AssignmentDetailsInteractionTest : ParentComposeTest() {
override fun displaysPageObjects() = Unit

private val assignmentDetailsPage = AssignmentDetailsPage(ModuleItemInteractions())
private val reminderPage = ReminderPage(composeTestRule)

@Test
fun testSubmissionStatus_Missing() {
Expand Down Expand Up @@ -242,132 +249,132 @@ class AssignmentDetailsInteractionTest : ParentComposeTest() {
}

@Test
fun testReminderSectionIsNotVisibleWhenThereIsNoFutureDueDate() {
@TestMetaData(Priority.IMPORTANT, FeatureCategory.ASSIGNMENTS, TestCategory.INTERACTION)
fun testReminderSectionIsVisibleWhenThereIsNoFutureDueDate() {
val data = setupData()
val course = data.courses.values.first()
val assignment = data.addAssignment(course.id, name = "Test Assignment", dueAt = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, -1)
}.time.toApiString())
gotoAssignment(data, assignment)

assignmentDetailsPage.assertReminderSectionNotDisplayed()
reminderPage.assertReminderSectionDisplayed()
}

@Test
fun testReminderSectionIsVisibleWhenThereIsFutureDueDate() {
@TestMetaData(Priority.IMPORTANT, FeatureCategory.ASSIGNMENTS, TestCategory.INTERACTION)
fun testReminderSectionIsVisibleWhenThereIsNoDueDate() {
val data = setupData()
val course = data.courses.values.first()
val assignment = data.addAssignment(course.id, name = "Test Assignment", dueAt = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, 1)
}.time.toApiString())
val assignment = data.addAssignment(course.id, name = "Test Assignment")
gotoAssignment(data, assignment)

assignmentDetailsPage.assertReminderSectionDisplayed()
reminderPage.assertReminderSectionDisplayed()
}

@Test
fun testAddReminder() {
@TestMetaData(Priority.IMPORTANT, FeatureCategory.ASSIGNMENTS, TestCategory.INTERACTION)
fun testReminderSectionIsVisibleWhenThereIsFutureDueDate() {
val data = setupData()
val course = data.courses.values.first()
val assignment = data.addAssignment(course.id, name = "Test Assignment", dueAt = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, 1)
}.time.toApiString())
gotoAssignment(data, assignment)

assignmentDetailsPage.clickAddReminder()
assignmentDetailsPage.selectTimeOption("1 Hour Before")

assignmentDetailsPage.assertReminderDisplayedWithText("1 Hour Before")
reminderPage.assertReminderSectionDisplayed()
}

@Test
fun testRemoveReminder() {
@TestMetaData(Priority.MANDATORY, FeatureCategory.ASSIGNMENTS, TestCategory.INTERACTION)
fun testAddReminder() {
val reminderCalendar = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, 1)
}
val data = setupData()
val course = data.courses.values.first()
val assignment = data.addAssignment(course.id, name = "Test Assignment", dueAt = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, 1)
add(Calendar.DAY_OF_MONTH, 2)
}.time.toApiString())
gotoAssignment(data, assignment)

assignmentDetailsPage.clickAddReminder()
assignmentDetailsPage.selectTimeOption("1 Hour Before")

assignmentDetailsPage.assertReminderDisplayedWithText("1 Hour Before")
reminderPage.clickAddReminder()
reminderPage.clickCustomReminderOption()
reminderPage.selectDate(reminderCalendar)
reminderPage.selectTime(reminderCalendar)

assignmentDetailsPage.removeReminderWithText("1 Hour Before")

assignmentDetailsPage.assertReminderNotDisplayedWithText("1 Hour Before")
reminderPage.assertReminderDisplayedWithText(reminderCalendar.time.toFormattedString())
}

@Test
fun testAddCustomReminder() {
@TestMetaData(Priority.MANDATORY, FeatureCategory.ASSIGNMENTS, TestCategory.INTERACTION)
fun testRemoveReminder() {
val reminderCalendar = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, 1)
}
val data = setupData()
val course = data.courses.values.first()
val assignment = data.addAssignment(course.id, name = "Test Assignment", dueAt = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, 1)
add(Calendar.DAY_OF_MONTH, 2)
}.time.toApiString())
gotoAssignment(data, assignment)

assignmentDetailsPage.clickAddReminder()
assignmentDetailsPage.clickCustom()
assignmentDetailsPage.assertDoneButtonIsDisabled()
assignmentDetailsPage.fillQuantity("15")
assignmentDetailsPage.assertDoneButtonIsDisabled()
assignmentDetailsPage.clickHoursBefore()
assignmentDetailsPage.clickDone()
reminderPage.clickAddReminder()
reminderPage.clickCustomReminderOption()
reminderPage.selectDate(reminderCalendar)
reminderPage.selectTime(reminderCalendar)

assignmentDetailsPage.assertReminderDisplayedWithText("15 Hours Before")

reminderPage.assertReminderDisplayedWithText(reminderCalendar.time.toFormattedString())

reminderPage.removeReminderWithText(reminderCalendar.time.toFormattedString())

reminderPage.assertReminderNotDisplayedWithText(reminderCalendar.time.toFormattedString())
}

@Test
@TestMetaData(Priority.IMPORTANT, FeatureCategory.ASSIGNMENTS, TestCategory.INTERACTION)
fun testAddReminderInPastShowsError() {
val reminderCalendar = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, -1)
}
val data = setupData()
val course = data.courses.values.first()
val assignment = data.addAssignment(course.id, name = "Test Assignment", dueAt = Calendar.getInstance().apply {
add(Calendar.MINUTE, 30)
}.time.toApiString())
gotoAssignment(data, assignment)

assignmentDetailsPage.clickAddReminder()
assignmentDetailsPage.selectTimeOption("1 Hour Before")
reminderPage.clickAddReminder()
reminderPage.clickCustomReminderOption()
reminderPage.selectDate(reminderCalendar)
reminderPage.selectTime(reminderCalendar)

checkToastText(R.string.reminderInPast, activityRule.activity)
}

@Test
@TestMetaData(Priority.IMPORTANT, FeatureCategory.ASSIGNMENTS, TestCategory.INTERACTION)
fun testAddReminderForTheSameTimeShowsError() {
val data = setupData()
val course = data.courses.values.first()
val assignment = data.addAssignment(course.id, name = "Test Assignment", dueAt = Calendar.getInstance().apply {
val reminderCalendar = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, 1)
}.time.toApiString())
gotoAssignment(data, assignment)

assignmentDetailsPage.clickAddReminder()
assignmentDetailsPage.selectTimeOption("1 Hour Before")
assignmentDetailsPage.clickAddReminder()
assignmentDetailsPage.selectTimeOption("1 Hour Before")

checkToastText(R.string.reminderAlreadySet, activityRule.activity)
}

@Test
fun testAddReminderForTheSameTimeWithDifferentMeasureOfTimeShowsError() {
}
val data = setupData()
val course = data.courses.values.first()
val assignment = data.addAssignment(course.id, name = "Test Assignment", dueAt = Calendar.getInstance().apply {
add(Calendar.DAY_OF_MONTH, 10)
add(Calendar.DAY_OF_MONTH, 2)
}.time.toApiString())
gotoAssignment(data, assignment)

assignmentDetailsPage.clickAddReminder()
assignmentDetailsPage.selectTimeOption("1 Week Before")
assignmentDetailsPage.clickAddReminder()
reminderPage.clickAddReminder()
reminderPage.clickCustomReminderOption()
reminderPage.selectDate(reminderCalendar)
reminderPage.selectTime(reminderCalendar)

assignmentDetailsPage.clickCustom()
assignmentDetailsPage.fillQuantity("7")
assignmentDetailsPage.clickDaysBefore()
assignmentDetailsPage.clickDone()
reminderPage.clickAddReminder()
reminderPage.clickCustomReminderOption()
reminderPage.selectDate(reminderCalendar)
reminderPage.selectTime(reminderCalendar)

checkToastText(R.string.reminderAlreadySet, activityRule.activity)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,8 @@ class ParentAssignmentDetailsBehaviour @Inject constructor(
private fun getContextURL(courseId: Long, assignmentId: Long): String {
return "${apiPrefs.fullDomain}/courses/$courseId/assignments/$assignmentId"
}

override fun getThemeColor(course: Course): Int {
return parentPrefs.currentStudent.studentColor
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import com.instructure.parentapp.R
import com.instructure.parentapp.features.main.MainActivity

class ParentAlarmReceiverNotificationHandler: AlarmReceiverNotificationHandler {
override fun showNotification(context: Context, assignmentId: Long, assignmentPath: String, assignmentName: String, dueIn: String) {
val intent = MainActivity.createIntent(context, Uri.parse(assignmentPath))
override fun showNotification(context: Context, contentId: Long, htmlPath: String, title: String, message: String) {
val intent = MainActivity.createIntent(context, Uri.parse(htmlPath))

val pendingIntent = PendingIntent.getActivity(
context, 0, intent,
Expand All @@ -37,14 +37,14 @@ class ParentAlarmReceiverNotificationHandler: AlarmReceiverNotificationHandler {

val builder = NotificationCompat.Builder(context, AlarmReceiver.CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification_canvas_logo)
.setContentTitle(context.getString(R.string.reminderNotificationTitle))
.setContentText(context.getString(R.string.reminderNotificationDescription, dueIn, assignmentName))
.setContentTitle(title)
.setContentText(message)
.setAutoCancel(true)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)

val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.notify(assignmentId.toInt(), builder.build())
notificationManager.notify(contentId.toInt(), builder.build())
}

override fun createNotificationChannel(context: Context) {
Expand Down
Loading