Skip to content
test_content.py 46.4 KiB
Newer Older
        factories.EventFactory(
            course=self.course, kind="homework_due", ordinal=1,
            time=time)
        self.assertEqual(
            content.parse_date_spec(self.course, datespec, vctx=self.vctx),
            datetime.datetime(2019, 1, 1, tzinfo=pytz.UTC))
        self.assertEqual(self.mock_add_warning.call_count, 0)

    def test_plus_weeks(self):
        datespec = "homework_due 1 + 2 weeks"

        time = datetime.datetime(2018, 12, 31, tzinfo=pytz.UTC)
        factories.EventFactory(
            course=self.course, kind="homework_due", ordinal=1,
            time=time)
        self.assertEqual(
            content.parse_date_spec(self.course, datespec, vctx=self.vctx),
            datetime.datetime(2019, 1, 14, tzinfo=pytz.UTC))
        self.assertEqual(self.mock_add_warning.call_count, 0)

    def test_plus_minutes(self):
        datespec = "homework_due 1 +     2 hour - 59 minutes"

        time = datetime.datetime(2018, 12, 31, tzinfo=pytz.UTC)
        factories.EventFactory(
            course=self.course, kind="homework_due", ordinal=1,
            time=time)
        self.assertEqual(
            content.parse_date_spec(self.course, datespec, vctx=self.vctx),
            datetime.datetime(2018, 12, 31, 1, 1, tzinfo=pytz.UTC))
        self.assertEqual(self.mock_add_warning.call_count, 0)

    def test_plus_invalid_time_unit(self):
        datespec = "homework_due 1 + 2 foos"

        time = datetime.datetime(2018, 12, 31, tzinfo=pytz.UTC)
        factories.EventFactory(
            course=self.course, kind="homework_due", ordinal=1,
            time=time)
        from course.validation import ValidationError
        with self.assertRaises(ValidationError) as cm:
            content.parse_date_spec(self.course, datespec, vctx=self.vctx)

        expected_error_msg = "invalid identifier '%s'" % datespec
        self.assertIn(expected_error_msg, str(cm.exception))

        # no vctx
        self.assertEqual(
            content.parse_date_spec(self.course, datespec), self.mock_now_value)

    def test_is_end(self):
        datespec = "end:homework_due 1 + 25 hours"

        time = datetime.datetime(2018, 12, 30, 23, tzinfo=pytz.UTC)
        evt = factories.EventFactory(
            course=self.course, kind="homework_due", ordinal=1,
            time=time)

        # event has no end_time, no vctx
        self.assertEqual(
            content.parse_date_spec(self.course, datespec),
            datetime.datetime(2019, 1, 1, tzinfo=pytz.UTC))

        # event has no end_time, no vctx
        self.assertEqual(
            content.parse_date_spec(self.course, datespec, vctx=self.vctx),
            datetime.datetime(2019, 1, 1, tzinfo=pytz.UTC))
        self.assertEqual(self.mock_add_warning.call_count, 1)
        expected_warning_msg = (
            "event '%s' has no end time, using start time instead"
            % datespec)
        self.assertIn(expected_warning_msg, self.mock_add_warning.call_args[0])
        self.mock_add_warning.reset_mock()

        # update event with end_time
        evt.time -= datetime.timedelta(days=1)
        evt.end_time = time
        evt.save()

        self.assertEqual(
            content.parse_date_spec(self.course, datespec, vctx=self.vctx),
            datetime.datetime(2019, 1, 1, tzinfo=pytz.UTC))
        self.assertEqual(self.mock_add_warning.call_count, 0)


class GetFlowPageDescTest(SingleCoursePageTestMixin, TestCase):
    # test content.get_flow_desc

    @classmethod
    def setUpTestData(cls):  # noqa
        super(GetFlowPageDescTest, cls).setUpTestData()
        cls.flow_desc = cls.get_hacked_flow_desc()

    def test_success(self):
        self.assertEqual(
            content.get_flow_page_desc(
                flow_id=self.flow_id,
                flow_desc=self.flow_desc,
                group_id="intro",
                page_id="welcome").id, "welcome")

        self.assertEqual(
            content.get_flow_page_desc(
                flow_id=self.flow_id,
                flow_desc=self.flow_desc,
                group_id="quiz_tail",
                page_id="addition").id, "addition")

    def test_flow_page_desc_does_not_exist(self):
        with self.assertRaises(ObjectDoesNotExist):
            content.get_flow_page_desc(
                self.flow_id, self.flow_desc, "quiz_start", "unknown_page")

        with self.assertRaises(ObjectDoesNotExist):
            content.get_flow_page_desc(
                self.flow_id, self.flow_desc, "unknown_group", "unknown_page")


class GetFlowPageClassTest(SingleCourseTestMixin, TestCase):
    # test content.get_flow_page_class

    def get_pctx(self, commit_sha=None):
        if commit_sha is not None:
            self.course.active_git_commit_sha = commit_sha
            self.course.save()
            self.course.refresh_from_db()

        rf = RequestFactory()
        request = rf.get(self.get_course_page_url())
        request.user = self.instructor_participation.user

        from course.utils import CoursePageContext
        return CoursePageContext(request, self.course.identifier)

    def test_built_in_class(self):
        repo = mock.MagicMock()
        commit_sha = mock.MagicMock()
        self.assertEqual(
            content.get_flow_page_class(repo, "TextQuestion", commit_sha),
            page.TextQuestion)

    def test_class_not_found_dot_path_length_1(self):
        repo = mock.MagicMock()
        commit_sha = mock.MagicMock()
        with self.assertRaises(content.ClassNotFoundError):
            content.get_flow_page_class(repo, "UnknownClass", commit_sha)

    def test_class_not_found_module_not_exist(self):
        repo = mock.MagicMock()
        commit_sha = mock.MagicMock()
        with self.assertRaises(content.ClassNotFoundError):
            content.get_flow_page_class(
                repo, "mypackage.UnknownClass", commit_sha)

    def test_class_not_found_module_does_not_exist(self):
        repo = mock.MagicMock()
        commit_sha = mock.MagicMock()
        with self.assertRaises(content.ClassNotFoundError):
            content.get_flow_page_class(
                repo, "mypackage.UnknownClass", commit_sha)

    def test_class_not_found_last_component_does_not_exist(self):
        repo = mock.MagicMock()
        commit_sha = mock.MagicMock()
        with self.assertRaises(content.ClassNotFoundError):
            content.get_flow_page_class(
                repo, "tests.resource.UnknownClass", commit_sha)

    def test_found_by_dotted_path(self):
        repo = mock.MagicMock()
        commit_sha = mock.MagicMock()
        from tests.resource import MyFakeQuestionType
        self.assertEqual(
            content.get_flow_page_class(
                repo, "tests.resource.MyFakeQuestionType", commit_sha),
            MyFakeQuestionType)

    def test_repo_path_length_1(self):
        repo = mock.MagicMock()
        commit_sha = mock.MagicMock()
        type_name = "repo:UnknownClass"
        with self.assertRaises(content.ClassNotFoundError) as cm:

            content.get_flow_page_class(
                repo, type_name, commit_sha)

        expected_error_msg = (
            "repo page class must conist of two "
            "dotted components (invalid: '%s')"
            % type_name)

        self.assertIn(expected_error_msg, str(cm.exception))

    def test_repo_path_length_3(self):
        repo = mock.MagicMock()
        commit_sha = mock.MagicMock()
        type_name = "repo:mydir.mymodule.UnknownClass"
        with self.assertRaises(content.ClassNotFoundError) as cm:
            content.get_flow_page_class(
                repo, type_name, commit_sha)

        expected_error_msg = (
            "repo page class must conist of two "
            "dotted components (invalid: '%s')"
            % type_name)

        self.assertIn(expected_error_msg, str(cm.exception))

    def test_repo_class_not_exist(self):
        with self.get_pctx(commit_sha=COMMIT_SHA_SUPPORT_CUSTOM_PAGES).repo as repo:
            with self.assertRaises(content.ClassNotFoundError):
                content.get_flow_page_class(
                    repo, "repo:simple_questions.Unknown",
                    commit_sha=COMMIT_SHA_SUPPORT_CUSTOM_PAGES.encode())

    def test_repo_class_found(self):
        with self.get_pctx(commit_sha=COMMIT_SHA_SUPPORT_CUSTOM_PAGES).repo as repo:
            content.get_flow_page_class(
                repo, "repo:simple_questions.MyTextQuestion",
                commit_sha=COMMIT_SHA_SUPPORT_CUSTOM_PAGES.encode())


class ListFlowIdsTest(unittest.TestCase):
    # test content.list_flow_ids
    def setUp(self):
        fake_get_repo_blob = mock.patch("course.content.get_repo_blob")
        self.mock_get_repo_blob = fake_get_repo_blob.start()
        self.addCleanup(fake_get_repo_blob.stop)
        self.repo = mock.MagicMock()
        self.commit_sha = mock.MagicMock()

    def test_object_does_not_exist(self):
        self.mock_get_repo_blob.side_effect = ObjectDoesNotExist()
        self.assertEqual(content.list_flow_ids(self.repo, self.commit_sha), [])

    def test_result(self):
        tree = Tree()
        tree.add(b"not_a_flow.txt", stat.S_IFREG, b"not a flow")
        tree.add(b"flow_b.yml", stat.S_IFREG, b"flow_b content")
        tree.add(b"flow_a.yml", stat.S_IFREG, b"flow_a content")
        tree.add(b"flow_c.yml", stat.S_IFREG, b"flow_c content")
        tree.add(b"temp_dir", stat.S_IFDIR, b"a temp dir")

        self.mock_get_repo_blob.return_value = tree

        self.assertEqual(content.list_flow_ids(
            self.repo, self.commit_sha), ["flow_a", "flow_b", "flow_c"])

# vim: fdm=marker