diff --git a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/e2e/SpeedGraderE2ETest.kt b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/e2e/SpeedGraderE2ETest.kt new file mode 100644 index 0000000000..0d847fea3f --- /dev/null +++ b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/e2e/SpeedGraderE2ETest.kt @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2020 - present Instructure, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package com.instructure.teacher.ui.e2e + +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.action.ViewActions.click +import androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast +import androidx.test.espresso.matcher.ViewMatchers.withText +import com.instructure.canvas.espresso.E2E +import com.instructure.canvas.espresso.refresh +import com.instructure.canvas.espresso.withCustomConstraints +import com.instructure.dataseeding.api.SubmissionsApi +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.panda_annotations.FeatureCategory +import com.instructure.panda_annotations.Priority +import com.instructure.panda_annotations.TestCategory +import com.instructure.panda_annotations.TestMetaData +import com.instructure.teacher.R +import com.instructure.teacher.ui.utils.* +import org.junit.Test + +class SpeedGraderE2ETest : TeacherTest() { + override fun displaysPageObjects() = Unit + + override fun enableAndConfigureAccessibilityChecks() { + //We dont want to see accessibility errors on E2E tests + } + + @E2E + @Test + @TestMetaData(Priority.P0, FeatureCategory.GRADES, TestCategory.E2E) + fun testSpeedGraderE2E() { + val data = seedData(teachers = 1, courses = 1, students = 3, favoriteCourses = 1) + val teacher = data.teachersList[0] + val course = data.coursesList[0] + val student = data.studentsList[0] + val gradedStudent = data.studentsList[1] + val noSubStudent = data.studentsList[2] + + val assignment = seedAssignments( + courseId = course.id, + dueAt = 1.days.fromNow.iso8601, + submissionTypes = listOf(SubmissionType.ONLINE_TEXT_ENTRY), + teacherToken = teacher.token, + pointsPossible = 15.0 + ) + val sub = seedAssignmentSubmission( + submissionSeeds = listOf(SubmissionsApi.SubmissionSeedInfo( + amount = 1, + submissionType = SubmissionType.ONLINE_TEXT_ENTRY + )), + assignmentId = assignment[0].id, + courseId = course.id, + studentToken = student.token + ) + + val gradedSubmission = seedAssignmentSubmission( + submissionSeeds = listOf(SubmissionsApi.SubmissionSeedInfo( + amount = 1, + submissionType = SubmissionType.ONLINE_TEXT_ENTRY + )), + assignmentId = assignment[0].id, + courseId = course.id, + studentToken = gradedStudent.token + ) + + SubmissionsApi.gradeSubmission( + teacherToken = teacher.token, + courseId = course.id, + assignmentId = assignment[0].id, + studentId = gradedStudent.id, + postedGrade = "15", + excused = false + ) + + tokenLogin(teacher) + + coursesListPage.openCourse(course) + courseBrowserPage.openAssignmentsTab() + + assignmentListPage.clickAssignment(assignment[0]) + assignmentDetailsPage.assertHasSubmitted(actual = 1, outOf = 3) + assignmentDetailsPage.assertNotSubmitted(actual = 1, outOf = 3) + assignmentDetailsPage.openNotSubmittedSubmissions() + assignmentSubmissionListPage.assertHasStudentSubmission(canvasUser = noSubStudent) + assignmentSubmissionListPage.navigateBack() + assignmentDetailsPage.openGradedSubmissions() + assignmentSubmissionListPage.assertHasStudentSubmission(canvasUser = gradedStudent) + assignmentSubmissionListPage.navigateBack() + assignmentDetailsPage.openSubmissionsPage() + assignmentSubmissionListPage.clickSubmission(student) + speedGraderPage.assertDisplaysTextSubmissionViewWithStudentName(studentName = student.name) + speedGraderPage.selectGradesTab() + speedGraderGradePage.openGradeDialog() + val grade = "10" + speedGraderGradePage.enterNewGrade(grade) + speedGraderGradePage.assertHasGrade(grade) + speedGraderGradePage.navigateBack() + refresh() + + assignmentSubmissionListPage.clickFilterButton() + assignmentSubmissionListPage.clickFilterSubmissions() + assignmentSubmissionListPage.clickFilterUngraded() + assignmentSubmissionListPage.clickFilterDialogOk() + assignmentSubmissionListPage.assertHasNoSubmission() + + assignmentSubmissionListPage.clickFilterButton() + assignmentSubmissionListPage.clickFilterSubmissions() + onView(withText(R.string.not_submitted)).perform(withCustomConstraints(click(), isDisplayingAtLeast(10))) + assignmentSubmissionListPage.clickFilterDialogOk() + assignmentSubmissionListPage.assertHasSubmission(1) + } +} \ No newline at end of file diff --git a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/AssignmentDetailsPage.kt b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/AssignmentDetailsPage.kt index 6745f0fa7f..42ab1e2772 100644 --- a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/AssignmentDetailsPage.kt +++ b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/AssignmentDetailsPage.kt @@ -85,6 +85,18 @@ class AssignmentDetailsPage : BasePage(pageResId = R.id.assignmentDetailsPage) { viewAllSubmissions.click() } + fun openGradedSubmissions() { + gradedDonutWrapper.click() + } + + fun openUngradedSubmissions() { + ungradedDonutWrapper.click() + } + + fun openNotSubmittedSubmissions() { + notSubmittedDonutWrapper.click() + } + fun assertAssignmentDetails(assignment: Assignment) { assignmentNameTextView.assertHasText(assignment.name!!) if (assignment.published) { @@ -139,14 +151,14 @@ class AssignmentDetailsPage : BasePage(pageResId = R.id.assignmentDetailsPage) { pointsTextView.assertContainsText(newAssignmentPoints) } - fun assertHasSubmitted() { + fun assertHasSubmitted(actual: Int = 1, outOf: Int = 1) { val resources = InstrumentationRegistry.getTargetContext() - ungradedDonutWrapper.assertHasContentDescription(resources.getString(R.string.content_description_submission_donut_needs_grading).format(1, 1)) + ungradedDonutWrapper.assertHasContentDescription(resources.getString(R.string.content_description_submission_donut_needs_grading).format(actual, outOf)) } - fun assertNotSubmitted() { + fun assertNotSubmitted(actual: Int = 1, outOf: Int = 1) { val resources = InstrumentationRegistry.getTargetContext() - notSubmittedDonutWrapper.assertHasContentDescription(resources.getString(R.string.content_description_submission_donut_unsubmitted).format(1, 1)) + notSubmittedDonutWrapper.assertHasContentDescription(resources.getString(R.string.content_description_submission_donut_unsubmitted).format(actual, outOf)) } fun waitForRender() { diff --git a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/AssignmentSubmissionListPage.kt b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/AssignmentSubmissionListPage.kt index 449568253d..7148a04f54 100644 --- a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/AssignmentSubmissionListPage.kt +++ b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/AssignmentSubmissionListPage.kt @@ -15,18 +15,16 @@ */ package com.instructure.teacher.ui.pages -import androidx.test.espresso.matcher.ViewMatchers.withText +import androidx.test.espresso.matcher.ViewMatchers import com.instructure.canvas.espresso.waitForMatcherWithRefreshes import com.instructure.canvasapi2.models.User import com.instructure.dataseeding.model.CanvasUserApiModel import com.instructure.espresso.* -import com.instructure.espresso.page.BasePage +import com.instructure.espresso.page.* -import com.instructure.espresso.page.onViewWithText -import com.instructure.espresso.page.waitForViewWithId -import com.instructure.espresso.page.waitForViewWithText import com.instructure.teacher.R +import org.hamcrest.Matchers class AssignmentSubmissionListPage : BasePage() { @@ -38,7 +36,7 @@ class AssignmentSubmissionListPage : BasePage() { private val assignmentSubmissionClearFilter by OnViewWithId(R.id.clearFilterTextView, false) - private val assignmentSubmissionFilterButton by OnViewWithId(R.id.submissionFilter) + private val assignmentSubmissionFilterButton by OnViewWithId(R.id.submissionFilter, false) private val assignmentSubmissionFilterBySubmissionsButton by WaitForViewWithText(R.string.filterSubmissionsLowercase) @@ -75,6 +73,10 @@ class AssignmentSubmissionListPage : BasePage() { assignmentSubmissionClearFilter.assertGone() } + fun assertStudentHasGrade(grade: String) { + onView(withId(R.id.submissionGrade)).assertHasText(grade) + } + fun clickFilterButton() { assignmentSubmissionFilterButton.click() } @@ -105,8 +107,8 @@ class AssignmentSubmissionListPage : BasePage() { assignmentSubmissionListFilterLabel.assertHasText(text) } - fun assertHasSubmission() { - assignmentSubmissionRecyclerView.check(RecyclerViewItemCountAssertion(1)) + fun assertHasSubmission(expectedCount: Int = 1) { + assignmentSubmissionRecyclerView.check(RecyclerViewItemCountAssertion(expectedCount)) } fun assertHasNoSubmission() { @@ -156,4 +158,9 @@ class AssignmentSubmissionListPage : BasePage() { fun clickFilterDialogOk() { waitForViewWithText(android.R.string.ok).click() } + + fun navigateBack() { + onView(Matchers.allOf((withParent(R.id.assignmentSubmissionListToolbar) + ViewMatchers.withContentDescription("Navigate up")), ViewMatchers.isDisplayed())).click() + + } } diff --git a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/SpeedGraderGradePage.kt b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/SpeedGraderGradePage.kt index a9657d7aed..dc9980b5a5 100644 --- a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/SpeedGraderGradePage.kt +++ b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/SpeedGraderGradePage.kt @@ -15,11 +15,12 @@ */ package com.instructure.teacher.ui.pages +import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.withContentDescription import com.instructure.espresso.* -import com.instructure.espresso.page.BasePage -import com.instructure.espresso.page.getStringFromResource -import com.instructure.espresso.page.onViewWithId +import com.instructure.espresso.page.* import com.instructure.teacher.R +import org.hamcrest.Matchers class SpeedGraderGradePage : BasePage() { @@ -38,7 +39,7 @@ class SpeedGraderGradePage : BasePage() { fun openGradeDialog() { - gradeTextContainer.click() + onView(Matchers.allOf((withId(R.id.gradeTextContainer)), ViewMatchers.isDisplayed())).click() } fun enterNewGrade(grade: String) { @@ -46,13 +47,17 @@ class SpeedGraderGradePage : BasePage() { confirmDialogButton.click() } + fun navigateBack() { + onView(Matchers.allOf((withParent(R.id.speedGraderToolbar) + withContentDescription("Navigate up")), ViewMatchers.isDisplayed())).click() + } + fun assertGradeDialog() { customizeGradeTitle.assertDisplayed() excuseStudentCheckbox.assertDisplayed() } fun assertHasGrade(grade: String) { - gradeValueText.assertContainsText(grade) + onView(Matchers.allOf((withId(R.id.gradeValueText)), ViewMatchers.isDisplayed())).assertContainsText(grade) } fun assertRubricHidden() { diff --git a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/SpeedGraderPage.kt b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/SpeedGraderPage.kt index 8656c067d7..998907d343 100644 --- a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/SpeedGraderPage.kt +++ b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/pages/SpeedGraderPage.kt @@ -19,6 +19,7 @@ import androidx.annotation.StringRes import androidx.test.espresso.Espresso import androidx.test.espresso.NoMatchingViewException import androidx.test.espresso.matcher.ViewMatchers +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed import com.instructure.canvasapi2.models.Submission import com.instructure.canvasapi2.models.User import com.instructure.dataseeding.model.CanvasUserApiModel @@ -27,6 +28,7 @@ import com.instructure.espresso.* import com.instructure.espresso.page.* import com.instructure.teacher.R import org.hamcrest.Matchers +import org.hamcrest.Matchers.allOf @Suppress("unused") class SpeedGraderPage : BasePage() { @@ -57,7 +59,8 @@ class SpeedGraderPage : BasePage() { } fun selectGradesTab() { - gradeTab.click() + val gradesTabText = getStringFromResource(R.string.sg_tab_grade).toUpperCase() + onView(allOf((withText(gradesTabText)), isDisplayed())).click() } fun selectCommentsTab() { @@ -101,6 +104,10 @@ class SpeedGraderPage : BasePage() { waitForViewWithId(R.id.textSubmissionWebView).assertVisible() } + fun assertDisplaysTextSubmissionViewWithStudentName(studentName: String) { + onView(allOf(withText(studentName), isDisplayed())) + } + fun assertDisplaysEmptyState(@StringRes stringRes: Int) { waitForViewWithText(stringRes).assertCompletelyDisplayed() } diff --git a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/utils/TeacherTestExtensions.kt b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/utils/TeacherTestExtensions.kt index 12de3a53c1..c4fc512bcd 100644 --- a/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/utils/TeacherTestExtensions.kt +++ b/apps/teacher/src/androidTest/java/com/instructure/teacher/ui/utils/TeacherTestExtensions.kt @@ -129,6 +129,7 @@ fun TeacherTest.seedAssignments( lockAt: String = "", unlockAt: String = "", dueAt: String = "", + pointsPossible: Double? = null, submissionTypes: List = emptyList(), teacherToken: String): List { @@ -139,7 +140,8 @@ fun TeacherTest.seedAssignments( unlockAt = unlockAt, dueAt = dueAt, submissionTypes = submissionTypes, - teacherToken = teacherToken + teacherToken = teacherToken, + pointsPossible = pointsPossible ) return AssignmentsApi.seedAssignments(request, assignments) diff --git a/apps/teacher/src/main/res/layout/fragment_assignment_submission_list.xml b/apps/teacher/src/main/res/layout/fragment_assignment_submission_list.xml index 63e7f16c08..0c592aa41b 100644 --- a/apps/teacher/src/main/res/layout/fragment_assignment_submission_list.xml +++ b/apps/teacher/src/main/res/layout/fragment_assignment_submission_list.xml @@ -1,5 +1,4 @@ - -