def test_keep_graded(self): user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(description="some description", duration=30, course=course) GradedWorkFactory(course_task=task) data = { "course": str(task.course.id), "description": "new description", "duration": 15, "is_graded": "on", } with self.login(user): self.post("courses:task_edit", uuid=task.uuid, data=data) task.refresh_from_db() assert task.graded_work is not None assert GradedWork.objects.count() == 1
def test_only_task_for_grade_level(self): """Only general tasks and tasks for the student's grade level appear.""" user = self.make_user() enrollment = EnrollmentFactory( student__school=user.school, grade_level__school_year__school=user.school) course = CourseFactory(grade_levels=[enrollment.grade_level]) general_task = CourseTaskFactory(course=course) grade_level_task = CourseTaskFactory( course=course, grade_level=enrollment.grade_level) CourseTaskFactory(course=course, grade_level=GradeLevelFactory()) with self.login(user): self.get_check_200("students:course", uuid=enrollment.student.uuid, course_uuid=course.uuid) task_items = self.get_context("task_items") assert len(task_items) == 2 assert task_items[0]["course_task"] == general_task assert task_items[1]["course_task"] == grade_level_task
def test_two_school_years_same_week(self): """When two school years are in the same week, both are in the context.""" today = timezone.localdate() user = self.make_user() current_school_year = SchoolYearFactory( school=user.school, start_date=today + relativedelta(month=1, day=1), end_date=today + relativedelta(month=12, day=31), days_of_week=SchoolYear.ALL_DAYS, ) enrollment = EnrollmentFactory(grade_level__school_year=current_school_year) CourseTaskFactory(course__grade_levels=[enrollment.grade_level]) next_school_year = SchoolYearFactory( school=user.school, start_date=today + relativedelta(years=1, month=1, day=1), end_date=today + relativedelta(years=1, month=12, day=31), days_of_week=SchoolYear.ALL_DAYS, ) enrollment = EnrollmentFactory( grade_level__school_year=next_school_year, student__school=user.school ) task = CourseTaskFactory(course__grade_levels=[enrollment.grade_level]) week = Week(next_school_year.start_date) with self.login(user): self.get( "core:weekly", year=week.first_day.year, month=week.first_day.month, day=week.first_day.day, ) schedule = self.get_context("schedules")[0] assert schedule schedule = self.get_context("next_year_schedules")[0] course_day = {} for course_schedule_item in schedule["courses"][0]["days"]: if course_schedule_item["week_date"] == next_school_year.start_date: course_day = course_schedule_item assert course_day["task"] == task
def test_breaks_in_task_count(self): """A break is factored into the course task count.""" school_year = SchoolYearFactory(days_of_week=SchoolYear.ALL_DAYS) grade_level = GradeLevelFactory(school_year=school_year) course = CourseFactory( grade_levels=[grade_level], days_of_week=SchoolYear.ALL_DAYS ) SchoolBreakFactory( school_year=school_year, start_date=school_year.start_date, end_date=school_year.start_date, ) CourseTaskFactory(course=course) CourseTaskFactory(course=course) count = school_year.get_task_count_in_range( course, school_year.start_date, school_year.start_date + datetime.timedelta(days=1), ) assert count == 1
def test_error_no_tasks(self): """When no tasks are selected, inform the user.""" user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) CourseTaskFactory(course=course) data: dict = {} form = CourseTaskBulkDeleteForm(user=user, data=data) is_valid = form.is_valid() assert not is_valid assert "You need to select at least one task." in form.non_field_errors()
def test_hide_complete_tasks(self): """With students enrolled, completed tasks are hidden by default.""" user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(course=course) enrollment = EnrollmentFactory(grade_level=grade_level) CourseworkFactory(student=enrollment.student, course_task=task) with self.login(user): self.get_check_200("courses:detail", pk=course.id) assert not self.get_context("task_details")
def test_has_previous_task(self): """When the previous task is in the querystring, it's in the context.""" user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level], default_task_duration=42) task = CourseTaskFactory(course=course) url = self.reverse("courses:task_create_bulk", pk=course.id) url += f"?previous_task={task.id}" with self.login(user): self.get_check_200(url) assert self.get_context("previous_task") == task
def test_has_grade_levels(self): user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) other_grade_level = GradeLevelFactory( school_year=grade_level.school_year) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(course=course) with self.login(user): self.get("courses:task_edit", uuid=task.uuid) grade_levels = set(self.get_context("grade_levels")) assert grade_levels == {grade_level, other_grade_level}
def test_has_grade_levels(self): """The grade levels for selection match the grades that have the course.""" user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) other_grade_level = GradeLevelFactory(school_year=grade_level.school_year) course = CourseFactory(grade_levels=[grade_level, other_grade_level]) task = CourseTaskFactory(course=course) with self.login(user): self.get("courses:task_edit", pk=task.id) grade_levels = set(self.get_context("grade_levels")) assert grade_levels == {grade_level, other_grade_level}
def test_post(self): user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(description="some description", duration=30, course=course) data = { "course": str(task.course.id), "description": "new description", "duration": 15, } with self.login(user): response = self.post("courses:task_edit", uuid=task.uuid, data=data) task.refresh_from_db() assert task.description == data["description"] assert task.duration == data["duration"] self.response_302(response)
def test_has_previous_task(self): """The previous task is in the context if the querystring is present.""" user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(course=course) url = self.reverse("courses:task_create", pk=course.id) url += f"?previous_task={task.id}" with self.login(user): self.get(url) assert self.get_context("previous_task") == task
def test_has_tasks_with_completed(self): user = self.make_user() enrollment = EnrollmentFactory( student__school=user.school, grade_level__school_year__school=user.school) student = enrollment.student grade_level = enrollment.grade_level course = CourseFactory(grade_levels=[grade_level], days_of_week=Course.WEDNESDAY + Course.THURSDAY) task_1 = CourseTaskFactory(course=course) coursework = CourseworkFactory(course_task=task_1, student=student) task_2 = CourseTaskFactory(course=course) GradedWorkFactory(course_task=task_2) today = timezone.now().date() + datetime.timedelta(days=2) with self.login(user): self.get_check_200( "students:course", uuid=student.uuid, course_uuid=course.uuid, data={"completed_tasks": "1"}, ) self.assertContext( "task_items", [ { "course_task": task_1, "coursework": coursework, "has_graded_work": False, }, { "course_task": task_2, "planned_date": today, "has_graded_work": True }, ], )
def test_future_school_year_advanced_week(self): """Looking ahead in a future school year calculates offsets from year start. This is slightly different from looking at the first week of a school year that has a starting day before the school year starts. The primary functional difference is that the future school year will appear in the `schedules` context instead of `next_year_schedules` context. """ today = timezone.localdate() user = self.make_user() school_year = SchoolYearFactory( school=user.school, start_date=today + relativedelta(years=1, month=1, day=1), end_date=today + relativedelta(years=1, month=12, day=31), # Running only on the last possible day should guarantee 1 task/week. days_of_week=SchoolYear.SATURDAY, ) enrollment = EnrollmentFactory( grade_level__school_year=school_year, student__school=user.school ) course = CourseFactory( grade_levels=[enrollment.grade_level], days_of_week=Course.SATURDAY ) CourseTaskFactory(course=course) task = CourseTaskFactory(course=course) week = Week(school_year.start_date) first_day = week.first_day + datetime.timedelta(days=7) with self.login(user): self.get( "core:weekly", year=first_day.year, month=first_day.month, day=first_day.day, ) schedule = self.get_context("schedules")[0] assert schedule["courses"][0]["days"][0]["task"] == task
def test_week_schedule_no_tasks_end_of_week(self): """A student has no tasks to complete if the school week is over.""" today = datetime.date(2020, 5, 23) # A Saturday week = Week(today) enrollment = EnrollmentFactory( grade_level__school_year__start_date=today - datetime.timedelta(days=30)) student = enrollment.student school_year = enrollment.grade_level.school_year CourseTaskFactory(course__grade_levels=[enrollment.grade_level]) week_schedule = student.get_week_schedule(school_year, today, week) assert "task" not in week_schedule["courses"][0]["days"][0]
def test_redirect_next(self): next_url = "/another/location/" user = self.make_user() task = CourseTaskFactory( course__grade_level__school_year__school__admin=user) data = {"description": "new description", "duration": 15} url = self.reverse("courses:task_edit", uuid=task.uuid) url += f"?next={next_url}" with self.login(user): response = self.post(url, data=data) self.response_302(response) self.assertIn(next_url, response.get("Location"))
def test_other_user_task(self): """A task belonging to another user is a 404.""" user = self.make_user() student = StudentFactory(school=user.school) course_task = CourseTaskFactory() with self.login(user): response = self.get( "students:coursework", uuid=student.uuid, course_task_uuid=course_task.uuid, ) self.response_404(response)
def test_no_graded_work(self): """A course task that has no graded work returns a 404.""" user = self.make_user() student = StudentFactory(school=user.school) grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) course_task = CourseTaskFactory(course=course) with self.login(user): response = self.get( "students:grade_task", pk=student.id, course_task_id=course_task.id ) self.response_404(response)
def test_other_user_student(self): """A student belonging to another user is a 404.""" user = self.make_user() student = StudentFactory() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) course_task = CourseTaskFactory(course=course) with self.login(user): response = self.get( "students:coursework", pk=student.id, course_task_id=course_task.id ) self.response_404(response)
def test_get(self): user = self.make_user() student = StudentFactory(school=user.school) grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) course_task = CourseTaskFactory(course=course) with self.login(user): self.get_check_200( "students:coursework", pk=student.id, course_task_id=course_task.id ) assert self.get_context("student") == student assert self.get_context("course_task") == course_task
def test_post(self): user = self.make_user() course = CourseFactory(grade_level__school_year__school__admin=user) task = CourseTaskFactory(course=course) with self.login(user): response = self.post("courses:task_delete", uuid=course.uuid, task_uuid=task.uuid) self.assertEqual(CourseTask.objects.count(), 0) self.response_302(response) self.assertEqual(response.get("Location"), self.reverse("courses:detail", uuid=course.uuid))
def test_get_week_with_breaks(self): """Next week starts with the correct task when the current week has breaks.""" today = timezone.now().date() next_week = Week(today + datetime.timedelta(days=7)) enrollment = EnrollmentFactory() school_year = enrollment.grade_level.school_year student = enrollment.student course = CourseFactory(grade_levels=[enrollment.grade_level]) CourseworkFactory(student=student, course_task__course=course, completed_date=today) task = CourseTaskFactory(course=course) CourseTaskFactory(course=course) SchoolBreakFactory( school_year=school_year, start_date=today + datetime.timedelta(days=1), end_date=today + datetime.timedelta(days=2), ) week_schedule = student.get_week_schedule(school_year, today, next_week) assert week_schedule["courses"][0]["days"][0]["task"] == task
def test_do_not_show_course_when_no_days(self, timezone): now = datetime.datetime(2020, 1, 23, tzinfo=pytz.utc) thursday = now.date() timezone.localdate.return_value = now.date() user = self.make_user() student, grade_level = self.make_student_enrolled_in_grade_level(user, thursday) course = CourseFactory(grade_levels=[grade_level], days_of_week=Course.NO_DAYS) CourseTaskFactory(course=course) with self.login(user): self.get("core:app") schedules = self.get_context("schedules") assert schedules[0]["courses"] == []
def test_has_tasks_with_completed(self): """Completed tasks appear in the context when the query flag is present.""" user = self.make_user() enrollment = EnrollmentFactory( student__school=user.school, grade_level__school_year__school=user.school) student = enrollment.student grade_level = enrollment.grade_level course = CourseFactory(grade_levels=[grade_level]) task_1 = CourseTaskFactory(course=course) coursework = CourseworkFactory(course_task=task_1, student=student) task_2 = CourseTaskFactory(course=course) GradedWorkFactory(course_task=task_2) tuesday = timezone.localdate() + datetime.timedelta(days=1) with self.login(user): self.get_check_200( "students:course", uuid=student.uuid, course_uuid=course.uuid, data={"completed_tasks": "1"}, ) assert coursework.completed_date == timezone.localdate() assert self.get_context("task_items") == [ { "course_task": task_1, "coursework": coursework, "has_graded_work": False }, { "course_task": task_2, "planned_date": tuesday, "has_graded_work": True }, ]
def test_show_course_when_no_days_in_past(self, timezone): """When the week is in the past, show the course, even if it's not running.""" now = datetime.datetime(2020, 1, 25, tzinfo=pytz.utc) saturday = now.date() timezone.localdate.return_value = now.date() user = self.make_user() student, grade_level = self.make_student_enrolled_in_grade_level(user, saturday) course = CourseFactory(grade_levels=[grade_level], days_of_week=Course.NO_DAYS) CourseTaskFactory(course=course) with self.login(user): self.get("core:app") schedules = self.get_context("schedules") assert schedules[0]["courses"]
def test_post(self): user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(course=course) with self.login(user): response = self.post("courses:task_delete", uuid=course.uuid, task_uuid=task.uuid) assert CourseTask.objects.count() == 0 self.response_302(response) assert response.get("Location") == self.reverse("courses:detail", uuid=course.uuid)
def test_task_complete_one_student_coursework(self): """When a student has not completed, the task is marked incomplete.""" user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(course=course) EnrollmentFactory(grade_level=grade_level) enrollment = EnrollmentFactory(grade_level=grade_level) CourseworkFactory(student=enrollment.student, course_task=task) with self.login(user): self.get_check_200("courses:detail", pk=course.id) detail = self.get_context("task_details")[0] assert not detail["complete"]
def test_redirect_next(self): """The delete view redirects to next parameter if present.""" next_url = "/another/location/" user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(course=course) url = self.reverse("courses:task_delete", course_id=course.id, pk=task.id) url += f"?next={next_url}" with self.login(user): response = self.post(url) self.response_302(response) assert next_url in response.get("Location")
def test_get(self): user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level]) task = CourseTaskFactory(course=course) GradeFactory(graded_work__course_task=task) CourseworkFactory(course_task=task) CourseResourceFactory(course=course) with self.login(user): self.get_check_200("courses:delete", pk=course.id) assert self.get_context("tasks_count") == 1 assert self.get_context("grades_count") == 1 assert self.get_context("coursework_count") == 1 assert self.get_context("course_resources_count") == 1
def test_incomplete_daily(self): today = timezone.now().date() user = self.make_user() student = StudentFactory(school=user.school) grade_level = GradeLevelFactory(school_year__school=user.school) task = CourseTaskFactory(course__grade_levels=[grade_level]) CourseworkFactory(student=student, course_task=task) data = { "completed_date": "{:%Y-%m-%d}".format(today), f"task-{student.id}-{task.id}": "off", } with self.login(user): self.post("core:daily", data=data) assert not Coursework.objects.filter(student=student, course_task=task).exists()
def test_task_complete_grade_specific_task(self): """A grade specific task is complete when the students in the grade are done.""" user = self.make_user() grade_level = GradeLevelFactory(school_year__school=user.school) other_grade_level = GradeLevelFactory(school_year__school=user.school) course = CourseFactory(grade_levels=[grade_level, other_grade_level]) task = CourseTaskFactory(course=course, grade_level=grade_level) enrollment = EnrollmentFactory(grade_level=grade_level) CourseworkFactory(student=enrollment.student, course_task=task) EnrollmentFactory(grade_level=other_grade_level) url = self.reverse("courses:detail", pk=course.id) + "?completed_tasks=1" with self.login(user): self.get_check_200(url) detail = self.get_context("task_details")[0] assert detail["complete"]