Skip to content

Commit 29ec134

Browse files
authored
Merge pull request #3096 from instructure/release/student-7.14.0-278
Release Student 7.14.0 (278)
2 parents f4669e7 + 0028a2b commit 29ec134

File tree

306 files changed

+10477
-1892
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

306 files changed

+10477
-1892
lines changed

apps/buildSrc/src/main/java/GlobalDependencies.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
object Versions {
44
/* SDK Versions */
55
const val COMPILE_SDK = 35
6-
const val MIN_SDK = 26
6+
const val MIN_SDK = 28
77
const val TARGET_SDK = 35
88

99
/* Build/tooling */

apps/parent/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ android {
4040
applicationId "com.instructure.parentapp"
4141
minSdkVersion Versions.MIN_SDK
4242
targetSdkVersion Versions.TARGET_SDK
43-
versionCode 58
44-
versionName "4.2.0"
43+
versionCode 59
44+
versionName "4.3.0"
4545

4646
buildConfigField "boolean", "IS_TESTING", "false"
4747
testInstrumentationRunner 'com.instructure.parentapp.ui.espresso.ParentHiltTestRunner'

apps/parent/src/androidTest/java/com/instructure/parentapp/ui/e2e/AlertsE2ETest.kt

Lines changed: 113 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,7 @@ class AlertsE2ETest : ParentComposeTest() {
7171
studentAlertSettingsPage.clickThreshold(AlertType.ASSIGNMENT_MISSING)
7272
studentAlertSettingsPage.clickThreshold(AlertType.COURSE_ANNOUNCEMENT)
7373
studentAlertSettingsPage.clickThreshold(AlertType.INSTITUTION_ANNOUNCEMENT)
74-
studentAlertSettingsPage.clickThreshold(AlertType.ASSIGNMENT_GRADE_HIGH)
75-
studentAlertSettingsPage.enterThreshold("80")
76-
studentAlertSettingsPage.tapThresholdSaveButton()
74+
studentAlertSettingsPage.setThreshold(AlertType.ASSIGNMENT_GRADE_HIGH, "80")
7775

7876
Log.d(STEP_TAG, "Navigate back to Dashboard Page.")
7977
ViewUtils.pressBackButton(2)
@@ -119,10 +117,7 @@ class AlertsE2ETest : ParentComposeTest() {
119117
Log.d(STEP_TAG, "Change some alert settings")
120118
studentAlertSettingsPage.clickThreshold(AlertType.ASSIGNMENT_GRADE_HIGH)
121119
studentAlertSettingsPage.tapThresholdNeverButton()
122-
studentAlertSettingsPage.clickThreshold(AlertType.ASSIGNMENT_GRADE_LOW)
123-
studentAlertSettingsPage.enterThreshold("20")
124-
studentAlertSettingsPage.tapThresholdSaveButton()
125-
120+
studentAlertSettingsPage.setThreshold(AlertType.ASSIGNMENT_GRADE_LOW, "20")
126121

127122
Log.d(PREPARATION_TAG, "Seeding assignment for '${course.name}' course.")
128123
val testAssignmentBelow = AssignmentsApi.createAssignment(course.id, teacher.token, gradingType = GradingType.POINTS, pointsPossible = 20.0, dueAt = 1.days.fromNow.iso8601, submissionTypes = listOf(
@@ -182,9 +177,7 @@ class AlertsE2ETest : ParentComposeTest() {
182177

183178
Log.d(STEP_TAG, "Open the Student Alert Settings Page and enable alerts")
184179
manageStudentsPage.clickStudent(student.shortName)
185-
studentAlertSettingsPage.clickThreshold(AlertType.ASSIGNMENT_GRADE_HIGH)
186-
studentAlertSettingsPage.enterThreshold("80")
187-
studentAlertSettingsPage.tapThresholdSaveButton()
180+
studentAlertSettingsPage.setThreshold(AlertType.ASSIGNMENT_GRADE_HIGH, "80")
188181

189182
Log.d(STEP_TAG, "Navigate back to Dashboard Page.")
190183
ViewUtils.pressBackButton(2)
@@ -260,21 +253,10 @@ class AlertsE2ETest : ParentComposeTest() {
260253
studentAlertSettingsPage.clickThreshold(AlertType.COURSE_ANNOUNCEMENT)
261254
studentAlertSettingsPage.clickThreshold(AlertType.INSTITUTION_ANNOUNCEMENT)
262255

263-
studentAlertSettingsPage.clickThreshold(AlertType.ASSIGNMENT_GRADE_HIGH)
264-
studentAlertSettingsPage.enterThreshold("80")
265-
studentAlertSettingsPage.tapThresholdSaveButton()
266-
267-
studentAlertSettingsPage.clickThreshold(AlertType.ASSIGNMENT_GRADE_LOW)
268-
studentAlertSettingsPage.enterThreshold("20")
269-
studentAlertSettingsPage.tapThresholdSaveButton()
270-
271-
studentAlertSettingsPage.clickThreshold(AlertType.COURSE_GRADE_HIGH)
272-
studentAlertSettingsPage.enterThreshold("80")
273-
studentAlertSettingsPage.tapThresholdSaveButton()
274-
275-
studentAlertSettingsPage.clickThreshold(AlertType.COURSE_GRADE_LOW)
276-
studentAlertSettingsPage.enterThreshold("20")
277-
studentAlertSettingsPage.tapThresholdSaveButton()
256+
studentAlertSettingsPage.setThreshold(AlertType.ASSIGNMENT_GRADE_HIGH, "80")
257+
studentAlertSettingsPage.setThreshold(AlertType.ASSIGNMENT_GRADE_LOW, "20")
258+
studentAlertSettingsPage.setThreshold(AlertType.COURSE_GRADE_HIGH, "80")
259+
studentAlertSettingsPage.setThreshold(AlertType.COURSE_GRADE_LOW, "20")
278260

279261
Log.d(STEP_TAG, "Reopen the alerts screen")
280262
Espresso.pressBack()
@@ -354,4 +336,110 @@ class AlertsE2ETest : ParentComposeTest() {
354336
Log.d(ASSERTION_TAG, "Assert that the alerts are empty.")
355337
alertsPage.assertEmptyState()
356338
}
339+
340+
@E2E
341+
@Test
342+
@TestMetaData(Priority.NICE_TO_HAVE, FeatureCategory.ALERTS, TestCategory.E2E)
343+
fun testAlertsUndoMechanismE2E() {
344+
345+
Log.d(PREPARATION_TAG, "Seeding data.")
346+
val data = seedData(students = 1, courses = 1, teachers = 1, parents = 1)
347+
val course = data.coursesList[0]
348+
val parent = data.parentsList[0]
349+
val student = data.studentsList[0]
350+
val teacher = data.teachersList[0]
351+
352+
Log.d(STEP_TAG, "Login with user: '${parent.name}', login id: '${parent.loginId}'.")
353+
tokenLogin(parent)
354+
dashboardPage.waitForRender()
355+
356+
Log.d(STEP_TAG, "Open the Left Side Navigation Drawer menu.")
357+
dashboardPage.openLeftSideMenu()
358+
359+
Log.d(STEP_TAG, "Open the Manage Students Page.")
360+
leftSideNavigationDrawerPage.clickManageStudents()
361+
362+
Log.d(STEP_TAG, "Open the Student Alert Settings Page and enable some alerts.")
363+
manageStudentsPage.clickStudent(student.shortName)
364+
365+
studentAlertSettingsPage.setThreshold(AlertType.ASSIGNMENT_GRADE_HIGH, "80")
366+
studentAlertSettingsPage.setThreshold(AlertType.ASSIGNMENT_GRADE_LOW, "20")
367+
studentAlertSettingsPage.setThreshold(AlertType.COURSE_GRADE_HIGH, "80")
368+
369+
Log.d(STEP_TAG, "Reopen the alerts screen and refresh it.")
370+
Espresso.pressBack()
371+
manageStudentsPage.clickStudent(student.shortName)
372+
alertsPage.refresh()
373+
374+
Log.d(ASSERTION_TAG, "Assert that the alert settings are saved")
375+
studentAlertSettingsPage.assertPercentageThreshold(AlertType.ASSIGNMENT_GRADE_HIGH, "80%")
376+
studentAlertSettingsPage.assertPercentageThreshold(AlertType.ASSIGNMENT_GRADE_LOW, "20%")
377+
studentAlertSettingsPage.assertPercentageThreshold(AlertType.COURSE_GRADE_HIGH, "80%")
378+
379+
Log.d(STEP_TAG, "Navigate back to Dashboard Page.")
380+
ViewUtils.pressBackButton(2)
381+
382+
Log.d(STEP_TAG, "Open the Alerts Page.")
383+
dashboardPage.clickAlertsBottomMenu()
384+
385+
Log.d(PREPARATION_TAG, "Seeding assignment for '${course.name}' course.")
386+
val testAssignment = AssignmentsApi.createAssignment(course.id, teacher.token, gradingType = GradingType.POINTS, pointsPossible = 20.0, dueAt = 1.days.fromNow.iso8601, submissionTypes = listOf(
387+
SubmissionType.ONLINE_TEXT_ENTRY), assignmentName = "Test Assignment")
388+
389+
Log.d(PREPARATION_TAG, "Submit assignment: '${testAssignment.name}' for student: '${student.name}'.")
390+
SubmissionsApi.seedAssignmentSubmission(course.id, student.token, testAssignment.id, submissionSeedsList = listOf(
391+
SubmissionsApi.SubmissionSeedInfo(amount = 1, submissionType = SubmissionType.ONLINE_TEXT_ENTRY)))
392+
393+
Log.d(PREPARATION_TAG, "Grade submission: '${testAssignment.name}' with 18 points.")
394+
SubmissionsApi.gradeSubmission(teacher.token, course.id, testAssignment.id, student.id, postedGrade = "18")
395+
396+
Log.d(PREPARATION_TAG, "Seeding another assignment for '${course.name}' course.")
397+
val testAssignmentBelow = AssignmentsApi.createAssignment(course.id, teacher.token, gradingType = GradingType.POINTS, pointsPossible = 20.0, dueAt = 1.days.fromNow.iso8601, submissionTypes = listOf(
398+
SubmissionType.ONLINE_TEXT_ENTRY), assignmentName = "Test Assignment Below")
399+
400+
Log.d(PREPARATION_TAG, "Submit assignment: '${testAssignmentBelow.name}' for student: '${student.name}'.")
401+
SubmissionsApi.seedAssignmentSubmission(course.id, student.token, testAssignmentBelow.id, submissionSeedsList = listOf(
402+
SubmissionsApi.SubmissionSeedInfo(amount = 1, submissionType = SubmissionType.ONLINE_TEXT_ENTRY)))
403+
404+
Log.d(PREPARATION_TAG, "Grade submission: '${testAssignmentBelow.name}' with 1 points.")
405+
SubmissionsApi.gradeSubmission(teacher.token, course.id, testAssignmentBelow.id, student.id, postedGrade = "1")
406+
407+
Thread.sleep(5000) // Allow the grading to propagate
408+
val gradeBelowAlertTitle = "Assignment Grade Below 20"
409+
val gradeFilterLabel = "Course Grade Above 80"
410+
411+
Log.d(STEP_TAG, "Refresh the Alerts Page")
412+
alertsPage.refresh()
413+
414+
Log.d(ASSERTION_TAG, "Assert that the alerts are displayed.")
415+
alertsPage.assertAlertItemDisplayed(gradeBelowAlertTitle)
416+
alertsPage.assertAlertItemDisplayed("Assignment graded: 1 on Test Assignment Below in ${course.courseCode}")
417+
alertsPage.assertAlertItemDisplayed(gradeFilterLabel)
418+
alertsPage.assertAlertItemDisplayed("Course grade: 90.0% in ${course.courseCode}")
419+
alertsPage.assertAlertItemDisplayed("Assignment Grade Above 80")
420+
alertsPage.assertAlertItemDisplayed("Assignment graded: 18 on Test Assignment in ${course.courseCode}")
421+
422+
Log.d(STEP_TAG, "Dismiss the '$gradeBelowAlertTitle' alert.")
423+
alertsPage.dismissAlert("Assignment graded: 1 on Test Assignment Below in ${course.courseCode}")
424+
425+
Log.d(STEP_TAG, "Click on the UNDO button in the snackbar.")
426+
alertsPage.clickUndo()
427+
428+
Log.d(ASSERTION_TAG, "Assert that the '$gradeBelowAlertTitle' alert is displayed again and it is no longer marked as unread.")
429+
alertsPage.assertAlertItemDisplayed(gradeBelowAlertTitle)
430+
alertsPage.assertAlertItemDisplayed("Assignment graded: 1 on Test Assignment Below in ${course.courseCode}")
431+
alertsPage.assertAlertRead("Assignment graded: 1 on Test Assignment Below in ${course.courseCode}")
432+
433+
Log.d(STEP_TAG, "Dismiss the '$gradeFilterLabel' alert.")
434+
alertsPage.dismissAlert("Course grade: 90.0% in ${course.courseCode}")
435+
436+
Log.d(STEP_TAG, "Click on the UNDO button in the snackbar.")
437+
alertsPage.clickUndo()
438+
439+
Log.d(ASSERTION_TAG, "Assert that the '$gradeFilterLabel' alert is displayed again and it is no longer marked as unread same as the '$gradeBelowAlertTitle' alert.")
440+
alertsPage.assertAlertItemDisplayed(gradeFilterLabel)
441+
alertsPage.assertAlertItemDisplayed("Course grade: 90.0% in ${course.courseCode}")
442+
alertsPage.assertAlertRead("Course grade: 90.0% in ${course.courseCode}")
443+
}
444+
357445
}

apps/parent/src/androidTest/java/com/instructure/parentapp/ui/e2e/HelpMenuE2ETest.kt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@ import androidx.test.espresso.intent.Intents
2121
import com.instructure.canvas.espresso.E2E
2222
import com.instructure.canvas.espresso.FeatureCategory
2323
import com.instructure.canvas.espresso.Priority
24+
import com.instructure.canvas.espresso.Stub
2425
import com.instructure.canvas.espresso.TestCategory
2526
import com.instructure.canvas.espresso.TestMetaData
27+
import com.instructure.canvas.espresso.checkToastText
28+
import com.instructure.parentapp.R
2629
import com.instructure.parentapp.utils.ParentComposeTest
2730
import com.instructure.parentapp.utils.seedData
2831
import com.instructure.parentapp.utils.tokenLogin
@@ -39,6 +42,7 @@ class HelpMenuE2ETest : ParentComposeTest() {
3942
@E2E
4043
@Test
4144
@TestMetaData(Priority.NICE_TO_HAVE, FeatureCategory.DASHBOARD, TestCategory.E2E)
45+
@Stub
4246
fun testHelpMenuE2E() {
4347

4448
Log.d(PREPARATION_TAG, "Seeding data.")
@@ -67,6 +71,9 @@ class HelpMenuE2ETest : ParentComposeTest() {
6771
Log.d(ASSERTION_TAG, "Assert that the 'Report a Problem' dialog has displayed.")
6872
helpPage.assertReportProblemDialogDisplayed()
6973

74+
Log.d(STEP_TAG, "Click on 'Cancel' button on the 'Report a problem' dialog.")
75+
helpPage.clickCancelReportProblem()
76+
7077
Log.d(ASSERTION_TAG, "Assert that when clicking on the different help menu items then the corresponding intents will be fired and has the proper URLs.")
7178
Intents.init()
7279

@@ -79,4 +86,46 @@ class HelpMenuE2ETest : ParentComposeTest() {
7986
Intents.release()
8087
}
8188
}
89+
90+
@E2E
91+
@Test
92+
@TestMetaData(Priority.COMMON, FeatureCategory.DASHBOARD, TestCategory.E2E)
93+
@Stub
94+
fun testHelpMenuReportProblemE2E() {
95+
96+
Log.d(PREPARATION_TAG, "Seeding data.")
97+
val data = seedData(parents = 1, students = 1, courses = 1)
98+
val parent = data.parentsList[0]
99+
100+
Log.d(STEP_TAG, "Login with user: '${parent.name}', login id: '${parent.loginId}'.")
101+
tokenLogin(parent)
102+
dashboardPage.waitForRender()
103+
104+
Log.d(STEP_TAG, "Open the Left Side Navigation Drawer menu.")
105+
dashboardPage.openLeftSideMenu()
106+
107+
Log.d(STEP_TAG, "Open Help Menu.")
108+
leftSideNavigationDrawerPage.clickHelpMenu()
109+
110+
Log.d(ASSERTION_TAG, "Assert Help Menu Dialog is displayed.")
111+
helpPage.assertHelpMenuDisplayed()
112+
113+
Log.d(ASSERTION_TAG, "Assert that all the corresponding Help menu content are displayed.")
114+
helpPage.assertHelpMenuContent()
115+
116+
Log.d(STEP_TAG, "Click on the 'Report a Problem' help menu.")
117+
helpPage.clickReportProblemLabel()
118+
119+
Log.d(ASSERTION_TAG, "Assert that it is possible to write into the input fields and the corresponding buttons are displayed as well.")
120+
helpPage.assertReportProblemDialogDisplayed()
121+
122+
Log.d(STEP_TAG, "Fill in the 'Report a problem' form with subject and description.")
123+
helpPage.fillReportProblemForm("Test Subject", "Test Description")
124+
125+
Log.d(STEP_TAG, "Click on the 'Send' button on the 'Report a problem' dialog.")
126+
helpPage.clickSendReportProblem()
127+
128+
Log.d(ASSERTION_TAG, "Assert that the corresponding toast message is displayed.")
129+
checkToastText(R.string.errorReportThankyou, activityRule.activity)
130+
}
82131
}

apps/parent/src/androidTest/java/com/instructure/parentapp/ui/e2e/LoginE2ETest.kt

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class LoginE2ETest : ParentComposeTest() {
6464
Log.d(STEP_TAG, "Open the Left Side Navigation Drawer menu (to be able to log out).")
6565
dashboardPage.openLeftSideMenu()
6666

67-
Log.d(STEP_TAG, "Log out with '${student.name}' student.")
67+
Log.d(STEP_TAG, "Log out with '${parent.name}' student.")
6868
leftSideNavigationDrawerPage.logout()
6969

7070
Log.d(STEP_TAG, "Login with user: '${student.name}', login id: '${student.loginId}'.")
@@ -310,4 +310,89 @@ class LoginE2ETest : ParentComposeTest() {
310310
loginSignInPage.loginAs(user)
311311
}
312312

313+
@E2E
314+
@Test
315+
@TestMetaData(Priority.IMPORTANT, FeatureCategory.LOGIN, TestCategory.E2E)
316+
fun testLoginWithParentWhoHasNoStudentE2E() {
317+
318+
Log.d(PREPARATION_TAG, "Seeding data.")
319+
val data = seedData(students = 1, courses = 1, parents = 1)
320+
val parent = data.parentsList[0]
321+
val parentWithoutStudent = UserApi.createCanvasUser()
322+
val student = data.studentsList[0]
323+
324+
Log.d(STEP_TAG, "Login with user: '${parentWithoutStudent.name}', login id: '${parentWithoutStudent.loginId}'.")
325+
loginWithUser(parentWithoutStudent)
326+
327+
Log.d(ASSERTION_TAG, "Assert that the 'Not a Parent' page has been displayed with all the corresponding information on it.")
328+
notAParentPage.assertNotAParentPageDetails()
329+
330+
Log.d(STEP_TAG, "Click on 'Return to login' button to navigate back to the login page.")
331+
notAParentPage.clickReturnToLogin()
332+
333+
Log.d(STEP_TAG, "Login with user: '${parent.name}', login id: '${parent.loginId}'.")
334+
loginWithUser(parent, true)
335+
336+
Log.d(PREPARATION_TAG, "Generate a pairing code for the '${student.name}' student to be able to pair with an observer.")
337+
val responsePairingCodeObject = UserApi.postGeneratePairingCode(student.id)
338+
339+
Log.d(ASSERTION_TAG, "Assert that the Dashboard Page is the landing page and it is loaded successfully.")
340+
dashboardPage.waitForRender()
341+
dashboardPage.assertPageObjects()
342+
343+
Log.d(ASSERTION_TAG, "Assert that the '${parent.name}' parent user has logged in.")
344+
leftSideNavigationDrawerPage.assertUserLoggedIn(parent)
345+
346+
Log.d(STEP_TAG, "Open the Left Side Navigation Drawer menu.")
347+
dashboardPage.openLeftSideMenu()
348+
349+
Log.d(STEP_TAG, "Click on the 'Manage Students' button on the left-side menu.")
350+
leftSideNavigationDrawerPage.clickManageStudents()
351+
352+
Log.d(ASSERTION_TAG, "Assert that the 'Manage Students' page is displayed with the '${student.name}' student.")
353+
manageStudentsPage.assertToolbarTitle()
354+
manageStudentsPage.assertStudentItemDisplayed(student.shortName)
355+
356+
Log.d(STEP_TAG, "Click on the 'Add Student' FAB (+) button on the bottom-right corner.")
357+
manageStudentsPage.tapAddStudent()
358+
359+
Log.d(ASSERTION_TAG, "Assert that the 'Add student with...' label and both the 'Pairing Code' and the 'QR Code' options are displayed on the Add Student (bottom) Page.")
360+
addStudentBottomPage.assertAddStudentWithLabel()
361+
addStudentBottomPage.assertPairingCodeOptionDisplayed()
362+
addStudentBottomPage.assertQRCodeOptionDisplayed()
363+
364+
Log.d(STEP_TAG, "Click on the 'Pairing Code' to add a student via pairing code.")
365+
addStudentBottomPage.clickOnPairingCode()
366+
367+
Log.d(STEP_TAG, "Enter the pairing code of the student and click on the 'OK' button to apply.")
368+
pairingCodePage.enterPairingCode(responsePairingCodeObject.pairingCode.toString())
369+
pairingCodePage.clickOkButton()
370+
composeTestRule.waitForIdle()
371+
372+
Log.d(ASSERTION_TAG, "Assert that the '${student.shortName}' student is displayed.")
373+
manageStudentsPage.assertStudentItemDisplayed(student.shortName)
374+
375+
Log.d(STEP_TAG, "Click on the '${student.name}' student on the 'Manage Students' page.")
376+
manageStudentsPage.clickStudent(student.shortName)
377+
378+
Log.d(ASSERTION_TAG, "Assert that the 'Alert Settings' page is displayed.")
379+
studentAlertSettingsPage.assertToolbarTitle()
380+
381+
Log.d(STEP_TAG, "Click on the 'overflow menu' button on the 'Alert Settings' page.")
382+
studentAlertSettingsPage.clickOverflowMenu()
383+
384+
Log.d(STEP_TAG, "Click on the 'Delete Student' button on the overflow menu.")
385+
studentAlertSettingsPage.clickDeleteStudent()
386+
387+
Log.d(ASSERTION_TAG, "Assert that the 'Delete Student' dialog is displayed with the correct details.")
388+
studentAlertSettingsPage.assertDeleteStudentDialogDetails()
389+
390+
Log.d(STEP_TAG, "Click on the 'Delete' button on the 'Delete Student' dialog.")
391+
studentAlertSettingsPage.clickDeleteStudentButton()
392+
393+
Log.d(ASSERTION_TAG, "Assert that the previously deleted student is not displayed on the 'Manage Students' page anymore.")
394+
manageStudentsPage.assertStudentItemNotDisplayed(student.shortName)
395+
manageStudentsPage.assertEmptyContent()
396+
}
397+
313398
}

0 commit comments

Comments
 (0)