Example #1
0
    def test_no_student_forecast(self):
        """The forecaster can produce a forecast for no student."""
        enrollment = EnrollmentFactory()
        course = CourseFactory(grade_levels=[enrollment.grade_level])
        task = CourseTaskFactory(course=course)
        forecaster = Forecaster()

        items = forecaster.get_items_by_task(None, course)

        assert items[task]["planned_date"] == datetime.date.today()
Example #2
0
    def test_has_course(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):
            self.get("courses:task_edit", uuid=task.uuid)

        self.assertContext("course", task.course)
Example #3
0
    def test_after_task(self):
        user = self.make_user()
        grade_level = GradeLevelFactory(school_year__school=user.school)
        course = CourseFactory(grade_levels=[grade_level])
        data = {
            "course": str(course.id),
            "description": "A new task",
            "duration": "30"
        }
        task_1 = CourseTaskFactory(course=course)
        task_2 = CourseTaskFactory(course=course)
        url = self.reverse("courses:task_create", uuid=course.uuid)
        url += f"?previous_task={task_1.uuid}"

        with self.login(user):
            self.post(url, data=data)

        task_3 = CourseTask.objects.get(description="A new task")
        assert list(CourseTask.objects.all()) == [task_1, task_3, task_2]
Example #4
0
    def test_has_schedules(self, mock_timezone):
        friday = timezone.localdate() + relativedelta(weekday=FR)
        mock_timezone.localdate.return_value = friday
        user = self.make_user()
        student = StudentFactory(school=user.school)
        school_year = SchoolYearFactory(
            school=user.school, days_of_week=SchoolYear.FRIDAY
        )
        grade_level = GradeLevelFactory(school_year=school_year)
        course = CourseFactory(grade_levels=[grade_level], days_of_week=Course.FRIDAY)
        task_1 = CourseTaskFactory(course=course)
        coursework = CourseworkFactory(
            student=student, course_task=task_1, completed_date=friday
        )
        course_2 = CourseFactory(grade_levels=[grade_level], days_of_week=Course.FRIDAY)
        task_2a = CourseTaskFactory(course=course_2)
        CourseworkFactory(
            student=student,
            course_task=task_2a,
            completed_date=friday - datetime.timedelta(days=1),
        )
        task_2b = CourseTaskFactory(course=course_2)
        course_3 = CourseFactory(
            grade_levels=[grade_level], days_of_week=Course.THURSDAY
        )
        CourseTaskFactory(course=course_3)
        course_4 = CourseFactory(grade_levels=[grade_level], days_of_week=Course.FRIDAY)
        EnrollmentFactory(student=student, grade_level=grade_level)

        with self.login(user):
            self.get("core:daily")

        expected_schedule = {
            "student": student,
            "courses": [
                {"course": course, "coursework": [coursework]},
                {"course": course_2, "task": task_2b},
                {"course": course_3},
                {"course": course_4, "no_scheduled_task": True},
            ],
        }
        self.assertContext("schedules", [expected_schedule])
Example #5
0
    def test_no_students_with_task(self):
        """Even when no student exists, the start banner may appear."""
        user = self.make_user()
        grade_level = GradeLevelFactory(school_year__school=user.school)
        CourseTaskFactory(course__grade_levels=[grade_level])

        with self.login(user):
            self.get_check_200("core:daily")

        assert not self.get_context("has_students")
        assert self.get_context("has_tasks")
Example #6
0
    def test_delete(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.delete("courses:task_hx_delete", uuid=task.uuid)

        assert CourseTask.objects.count() == 0
        self.response_200(response)
Example #7
0
    def test_ok(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):
            self.get_check_200("core:start-course-task")

        assert self.get_context("course") == course
        assert self.get_context("task") == task
Example #8
0
    def test_only_users_course_task(self):
        """The task must belong to the user."""
        user = self.make_user()
        grade_level = GradeLevelFactory(school_year__school=user.school)
        CourseFactory(grade_levels=[grade_level])
        CourseTaskFactory()

        with self.login(user):
            self.get_check_200("core:start-course-task")

        assert self.get_context("task") is None
Example #9
0
    def test_grade_level_name_with_task(self):
        """Any grade level specific task has the grade level's name next to it."""
        user = self.make_user()
        grade_level = GradeLevelFactory(school_year__school=user.school)
        course = CourseFactory(grade_levels=[grade_level])
        CourseTaskFactory(course=course, grade_level=grade_level)

        with self.login(user):
            self.get("courses:detail", pk=course.id)

        self.assertResponseContains(grade_level.name)
Example #10
0
    def test_only_delete_users_tasks(self):
        """A user may only delete tasks for their school."""
        user = self.make_user()
        grade_level = GradeLevelFactory(school_year__school=user.school)
        course = CourseFactory(grade_levels=[grade_level])
        task_to_delete = CourseTaskFactory(course=course)
        another_task = CourseTaskFactory()
        data = {
            f"task-{task_to_delete.id}": str(task_to_delete.id),
            f"task-{another_task.id}": str(another_task.id),
        }
        form = CourseTaskBulkDeleteForm(user=user, data=data)

        is_valid = form.is_valid()

        assert not is_valid
        assert (
            "Sorry, you do not have permission to delete the selected tasks."
            in form.non_field_errors()
        )
Example #11
0
    def test_post_other_user(self):
        user = self.make_user()
        course = CourseFactory()
        task = CourseTaskFactory(course=course)

        with self.login(user):
            response = self.get("courses:task_delete",
                                uuid=course.uuid,
                                task_uuid=task.uuid)

        self.response_404(response)
Example #12
0
    def test_delete_other_user(self):
        """Another user cannot delete a user's task."""
        user = self.make_user()
        course = CourseFactory()
        task = CourseTaskFactory(course=course)

        with self.login(user):
            response = self.delete("courses:task_hx_delete", pk=task.id)

        assert CourseTask.objects.count() == 1
        self.response_404(response)
Example #13
0
    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)
        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
Example #14
0
    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}
Example #15
0
    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", pk=student.id, course_task_id=course_task.id
            )

        self.response_404(response)
Example #16
0
    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
Example #17
0
    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
Example #18
0
    def test_task_complete_no_student(self):
        """When there are no students, a task defaults to incomplete."""
        user = self.make_user()
        grade_level = GradeLevelFactory(school_year__school=user.school)
        course = CourseFactory(grade_levels=[grade_level])
        CourseTaskFactory(course=course)

        with self.login(user):
            self.get_check_200("courses:detail", pk=course.id)

        detail = self.get_context("task_details")[0]
        assert not detail["complete"]
Example #19
0
    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", course_id=course.id, pk=task.id)

        assert CourseTask.objects.count() == 0
        self.response_302(response)
        assert response.get("Location") == self.reverse("courses:detail", pk=course.id)
Example #20
0
    def test_all_tasks_completed(self):
        """The last date matched the coursework completion."""
        enrollment = EnrollmentFactory()
        student = enrollment.student
        course = CourseFactory(grade_levels=[enrollment.grade_level])
        task = CourseTaskFactory(course=course)
        coursework = CourseworkFactory(student=student, course_task=task)
        forecaster = Forecaster()

        last_date = forecaster.get_last_forecast_date(student, course)

        assert last_date == coursework.completed_date
Example #21
0
    def test_no_student_planned_date(self):
        """When no student is enrolled, the tasks have a planned completion date."""
        user = self.make_user()
        grade_level = GradeLevelFactory(school_year__school=user.school)
        course = CourseFactory(grade_levels=[grade_level])
        CourseTaskFactory(course=course)

        with self.login(user):
            self.get_check_200("courses:detail", pk=course.id)

        planned_date = self.get_context("task_details")[0]["planned_date"]
        assert planned_date == datetime.date.today()
Example #22
0
    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}
Example #23
0
    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
Example #24
0
    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
Example #25
0
    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")
Example #26
0
    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()
Example #27
0
    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
Example #28
0
    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
                },
            ],
        )
Example #29
0
    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]
Example #30
0
    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"] == []