Skip to content

Commit

Permalink
[MBL-15817][Student] Important dates interaction tests (#1471)
Browse files Browse the repository at this point in the history
refs: MBL-15817
affects: Student
release note: none

test plan:
  • Loading branch information
hermannakos authored Feb 3, 2022
1 parent 6598069 commit 1396210
Show file tree
Hide file tree
Showing 18 changed files with 262 additions and 15 deletions.
2 changes: 1 addition & 1 deletion apps/student/flank_tablet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ gcloud:
record-video: true
timeout: 60m
test-targets:
- notAnnotation com.instructure.canvas.espresso.E2E, com.instructure.canvas.espresso.Stub
- notAnnotation com.instructure.canvas.espresso.E2E, com.instructure.canvas.espresso.Stub, com.instructure.canvas.espresso.StubTablet
device:
- model: Nexus9
version: 26
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Copyright (C) 2022 - present Instructure, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.instructure.student.ui.interaction

import com.instructure.canvas.espresso.StubTablet
import com.instructure.canvas.espresso.mockCanvas.*
import com.instructure.canvasapi2.models.Assignment
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.student.ui.pages.ElementaryDashboardPage
import com.instructure.student.ui.utils.StudentTest
import com.instructure.student.ui.utils.tokenLoginElementary
import dagger.hilt.android.testing.HiltAndroidTest
import org.junit.Test

@HiltAndroidTest
class ImportantDatesInteractionTest : StudentTest() {
override fun displaysPageObjects() = Unit

@Test
//The UI is different on tablet, so we only check the phone version
@StubTablet
@TestMetaData(Priority.P0, FeatureCategory.K5_DASHBOARD, TestCategory.INTERACTION)
fun testShowCalendarEvents() {
val data = createMockData(courseCount = 1)
val course = data.courses.values.toList()[0]

val event = data.addCourseCalendarEvent(course.id, 2.days.fromNow.iso8601, "Important event", "Important event description", true)

goToImportantDatesTab(data)
importantDatesPage.assertItemDisplayed(event.title!!)
}

@Test
@StubTablet
@TestMetaData(Priority.P0, FeatureCategory.K5_DASHBOARD, TestCategory.INTERACTION)
fun testShowAssignment() {
val data = createMockData(courseCount = 1)
val course = data.courses.values.toList()[0]

val assignment = data.addAssignment(courseId = course.id, submissionType = Assignment.SubmissionType.ONLINE_TEXT_ENTRY)
data.addAssignmentCalendarEvent(course.id, 2.days.fromNow.iso8601, assignment.name!!, assignment.description!!, true, assignment)

goToImportantDatesTab(data)
importantDatesPage.assertItemDisplayed(assignment.name!!)
}

@Test
@StubTablet
@TestMetaData(Priority.P0, FeatureCategory.K5_DASHBOARD, TestCategory.INTERACTION)
fun testEmptyView() {
val data = createMockData(courseCount = 1)

goToImportantDatesTab(data)

importantDatesPage.assertEmptyViewDisplayed()
}

@Test
@StubTablet
@TestMetaData(Priority.P1, FeatureCategory.K5_DASHBOARD, TestCategory.INTERACTION)
fun testPullToRefresh() {
val data = createMockData(courseCount = 1)
val course = data.courses.values.toList()[0]
data.addCourseCalendarEvent(course.id, 2.days.fromNow.iso8601, "Important event", "Important event description", true)

goToImportantDatesTab(data)
val eventToCheck = data.addCourseCalendarEvent(course.id, 2.days.fromNow.iso8601, "Important event 2", "Important event 2 description", true)

importantDatesPage.pullToRefresh()
importantDatesPage.assertItemDisplayed(eventToCheck.title!!)
}

@Test
@StubTablet
@TestMetaData(Priority.P1, FeatureCategory.K5_DASHBOARD, TestCategory.INTERACTION)
fun testOpenCalendarEvent() {
val data = createMockData(courseCount = 1)
val course = data.courses.values.toList()[0]
val event = data.addCourseCalendarEvent(course.id, 2.days.fromNow.iso8601, "Important event", "Important event description", true)

goToImportantDatesTab(data)
importantDatesPage.assertItemDisplayed(event.title!!)
importantDatesPage.clickImportantDatesItem(event.title!!)
calendarEventPage.verifyTitle(event.title!!)
calendarEventPage.verifyDescription(event.description!!)
}

@Test
@StubTablet
@TestMetaData(Priority.P1, FeatureCategory.K5_DASHBOARD, TestCategory.INTERACTION)
fun testOpenAssignment() {
val data = createMockData(courseCount = 1)
val course = data.courses.values.toList()[0]

val assignment = data.addAssignment(courseId = course.id, submissionType = Assignment.SubmissionType.ONLINE_TEXT_ENTRY)
data.addAssignmentCalendarEvent(course.id, 2.days.fromNow.iso8601, assignment.name!!, assignment.description!!, true, assignment)

goToImportantDatesTab(data)
importantDatesPage.assertItemDisplayed(assignment.name!!)
importantDatesPage.clickImportantDatesItem(assignment.name!!)
assignmentDetailsPage.verifyAssignmentDetails(assignment)
}

private fun goToImportantDatesTab(data: MockCanvas) {
val student = data.students[0]
val token = data.tokenFor(student)!!
tokenLoginElementary(data.domain, token, student)
elementaryDashboardPage.waitForRender()
elementaryDashboardPage.selectTab(ElementaryDashboardPage.ElementaryTabType.IMPORTANT_DATES)
//We need this to allow the ViewPager to switch tabs
Thread.sleep(100)
}

private fun createMockData(
courseCount: Int = 0,
withGradingPeriods: Boolean = false,
homeroomCourseCount: Int = 0): MockCanvas {

return MockCanvas.init(
studentCount = 1,
courseCount = courseCount,
withGradingPeriods = withGradingPeriods,
homeroomCourseCount = homeroomCourseCount)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class ElementaryDashboardPage : BasePage(R.id.elementaryDashboardPage) {
HOMEROOM(R.string.dashboardTabHomeroom),
SCHEDULE(R.string.dashboardTabSchedule),
GRADES(R.string.dashboardTabGrades),
RESOURCES(R.string.dashboardTabResources)
RESOURCES(R.string.dashboardTabResources),
IMPORTANT_DATES(R.string.dashboardTabImportantDates)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2022 - present Instructure, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.instructure.student.ui.pages

import com.instructure.espresso.assertDisplayed
import com.instructure.espresso.click
import com.instructure.espresso.page.*
import com.instructure.espresso.swipeDown
import com.instructure.student.R


class ImportantDatesPage : BasePage(R.id.importantDatesPage) {

fun assertItemDisplayed(itemName: String) {
waitForView(withAncestor(R.id.importantDatesRecyclerView) + withText(itemName)).assertDisplayed()
}

fun assertEmptyViewDisplayed() {
onView(withId(R.id.importantDatesEmptyView)).assertDisplayed()
}

fun pullToRefresh() {
onView(withId(R.id.importantDatesRecyclerView)).swipeDown()
}

fun clickImportantDatesItem(title: String) {
waitForView(withAncestor(R.id.importantDatesRecyclerView) + withText(title)).click()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ abstract class StudentTest : CanvasTest() {
val schedulePage = SchedulePage()
val gradesPage = GradesPage()
val resourcesPage = ResourcesPage()
val importantDatesPage = ImportantDatesPage()

// A no-op interaction to afford us an easy, harmless way to get a11y checking to trigger.
fun meaninglessSwipe() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ package com.instructure.student.mobius.elementary.importantdates

import androidx.fragment.app.FragmentActivity
import com.instructure.canvasapi2.models.CanvasContext
import com.instructure.canvasapi2.models.ScheduleItem
import com.instructure.pandautils.features.elementary.importantdates.ImportantDatesRouter
import com.instructure.student.fragment.CalendarEventFragment
import com.instructure.student.mobius.assignmentDetails.ui.AssignmentDetailsFragment
import com.instructure.student.router.RouteMatcher

class StudentImportantDatesRouter(private val activity: FragmentActivity) : ImportantDatesRouter {
override fun openCalendarEvent(canvasContext: CanvasContext, scheduleItemId: Long) {
RouteMatcher.route(activity, CalendarEventFragment.makeRoute(canvasContext, scheduleItemId))
override fun openCalendarEvent(canvasContext: CanvasContext, scheduleItem: ScheduleItem) {
RouteMatcher.route(activity, CalendarEventFragment.makeRoute(canvasContext, scheduleItem))
}

override fun openAssignment(canvasContext: CanvasContext, assignmentId: Long) {
Expand Down
2 changes: 1 addition & 1 deletion apps/teacher/flank_tablet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ gcloud:
record-video: true
timeout: 60m
test-targets:
- notAnnotation com.instructure.canvas.espresso.E2E, com.instructure.canvas.espresso.Stub
- notAnnotation com.instructure.canvas.espresso.E2E, com.instructure.canvas.espresso.Stub, com.instructure.canvas.espresso.StubTablet
device:
- model: Nexus9
version: 26
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
package com.instructure.teacher.features.elementary.importantdates

import com.instructure.canvasapi2.models.CanvasContext
import com.instructure.canvasapi2.models.ScheduleItem
import com.instructure.pandautils.features.elementary.importantdates.ImportantDatesRouter

class TeacherImportantDatesRouter : ImportantDatesRouter {

override fun openAssignment(canvasContext: CanvasContext, assignmentId: Long) = Unit

override fun openCalendarEvent(canvasContext: CanvasContext, scheduleItemId: Long) = Unit
override fun openCalendarEvent(canvasContext: CanvasContext, scheduleItem: ScheduleItem) = Unit
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (C) 2022 - present Instructure, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package com.instructure.canvas.espresso

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class StubTablet
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package com.instructure.canvas.espresso.mockCanvas

import android.util.Log
import com.github.javafaker.Bool
import com.github.javafaker.Faker
import com.instructure.canvas.espresso.mockCanvas.utils.Randomizer
import com.instructure.canvasapi2.models.*
Expand Down Expand Up @@ -541,7 +542,7 @@ fun MockCanvas.addUserPermissions(userId: Long, canUpdateName: Boolean, canUpdat
user?.permissions = CanvasContextPermission(canUpdateAvatar = canUpdateAvatar, canUpdateName = canUpdateName)
}

fun MockCanvas.addCourseCalendarEvent(courseId: Long, date: String, title: String, description: String) : ScheduleItem {
fun MockCanvas.addCourseCalendarEvent(courseId: Long, date: String, title: String, description: String, isImportantDate: Boolean = false) : ScheduleItem {
val newScheduleItem = ScheduleItem(
itemId = newItemId().toString(),
title = title,
Expand All @@ -550,7 +551,32 @@ fun MockCanvas.addCourseCalendarEvent(courseId: Long, date: String, title: Strin
isAllDay = true,
allDayAt = date,
startAt = date,
contextCode = "course_$courseId"
contextCode = "course_$courseId",
importantDates = isImportantDate
)

var calendarEventList = courseCalendarEvents[courseId]
if(calendarEventList == null) {
calendarEventList = mutableListOf<ScheduleItem>()
courseCalendarEvents[courseId] = calendarEventList
}
calendarEventList.add(newScheduleItem)

return newScheduleItem
}

fun MockCanvas.addAssignmentCalendarEvent(courseId: Long, date: String, title: String, description: String, isImportantDate: Boolean = false, assignment: Assignment): ScheduleItem {
val newScheduleItem = ScheduleItem(
itemId = newItemId().toString(),
title = title,
description = description,
itemType = ScheduleItem.Type.TYPE_ASSIGNMENT,
isAllDay = true,
allDayAt = date,
startAt = date,
contextCode = "course_$courseId",
importantDates = isImportantDate,
assignment = assignment
)

var calendarEventList = courseCalendarEvents[courseId]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ data class ScheduleItem(
val isHidden: Boolean = false,
@SerializedName("assignment_overrides")
val assignmentOverrides: List<AssignmentOverride?>? = arrayListOf(),
@SerializedName("important_dates")
val importantDates: Boolean = false,

// Not API related - Included here so they get parcelized
var submissionTypes: List<Assignment.SubmissionType> = ArrayList(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class ImportantDatesFragment : Fragment() {
is ImportantDatesAction.OpenAssignment -> router.openAssignment(action.canvasContext, action.assignmentId)
is ImportantDatesAction.OpenCalendarEvent -> router.openCalendarEvent(
action.canvasContext,
action.scheduleItemId
action.scheduleItem
)
is ImportantDatesAction.ShowToast -> {
Toast.makeText(requireContext(), action.toast, Toast.LENGTH_SHORT).show()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
package com.instructure.pandautils.features.elementary.importantdates

import com.instructure.canvasapi2.models.CanvasContext
import com.instructure.canvasapi2.models.ScheduleItem

interface ImportantDatesRouter {

fun openAssignment(canvasContext: CanvasContext, assignmentId: Long)

fun openCalendarEvent(canvasContext: CanvasContext, scheduleItemId: Long)
fun openCalendarEvent(canvasContext: CanvasContext, scheduleItem: ScheduleItem)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package com.instructure.pandautils.features.elementary.importantdates
import androidx.annotation.DrawableRes
import com.instructure.canvasapi2.models.CanvasContext
import com.instructure.canvasapi2.models.Course
import com.instructure.canvasapi2.models.ScheduleItem
import com.instructure.pandautils.features.elementary.importantdates.itemviewmodels.ImportantDatesHeaderItemViewModel
import com.instructure.pandautils.mvvm.ItemViewModel
import java.util.*
Expand All @@ -39,7 +40,7 @@ data class ImportantDatesItemViewData(

sealed class ImportantDatesAction {
data class OpenAssignment(val canvasContext: CanvasContext, val assignmentId: Long) : ImportantDatesAction()
data class OpenCalendarEvent(val canvasContext: CanvasContext, val scheduleItemId: Long) : ImportantDatesAction()
data class OpenCalendarEvent(val canvasContext: CanvasContext, val scheduleItem: ScheduleItem) : ImportantDatesAction()
data class ShowToast(val toast: String) : ImportantDatesAction()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class ImportantDatesViewModel @Inject constructor(
val canvasContext = CanvasContext.fromContextCode(course?.contextId)
if (scheduleItem != null && canvasContext != null) {
if (scheduleItem.assignment == null) {
_events.postValue(Event(ImportantDatesAction.OpenCalendarEvent(canvasContext, scheduleItemId)))
_events.postValue(Event(ImportantDatesAction.OpenCalendarEvent(canvasContext, scheduleItem)))
} else {
_events.postValue(Event(ImportantDatesAction.OpenAssignment(canvasContext, scheduleItem.assignment!!.id)))
}
Expand Down
Loading

0 comments on commit 1396210

Please sign in to comment.