From 731a1855cf9428bd8115c32da5cd40313984d11c Mon Sep 17 00:00:00 2001 From: Isuru Fernando Date: Thu, 17 Oct 2019 02:57:31 -0500 Subject: [PATCH] Test validation --- .../test_validate_course_content.py | 21 +++ .../test_validation/test_validation_tools.py | 121 ++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/tests/test_validation/test_validate_course_content.py b/tests/test_validation/test_validate_course_content.py index b4bf02cf9..39f18f87f 100644 --- a/tests/test_validation/test_validate_course_content.py +++ b/tests/test_validation/test_validate_course_content.py @@ -139,6 +139,11 @@ staticpage2_id = "spage2" staticpage2_desc = mock.MagicMock() +form1_path = "forms/form1.yml" +form1_location = "form1.yml" +form1_id = "form1" +form1_desc = mock.MagicMock() + flow1_path = "flows/flow1.yml" flow1_location = "flow1.yml" flow1_id = "flow1" @@ -203,6 +208,9 @@ def get_yaml_from_repo_safely_side_effect(repo, full_name, commit_sha): if full_name == staticpage2_path: return staticpage2_desc + if full_name == form1_path: + return form1_desc + return get_yaml_from_repo_safely(repo, full_name, commit_sha) @@ -223,6 +231,9 @@ def get_yaml_from_repo_safely_with_duplicate_grade_identifier_side_effect( if full_name == staticpage2_path: return staticpage2_desc + if full_name == form1_path: + return form1_desc + return get_yaml_from_repo_safely(repo, full_name, commit_sha) @@ -247,6 +258,7 @@ def get_repo_blob_side_effect(repo, full_name, commit_sha, allow_tree=True): if full_name == "forms": tree = Tree() tree.add(b"not_a_form", stat.S_IFREG, b"not a form") + tree.add(form1_location.encode(), stat.S_IFREG, b"a form") return tree if full_name == "": return Tree() @@ -343,6 +355,11 @@ def setUp(self): self.mock_validate_staticpage_desc = fake_validate_staticpage_desc.start() self.addCleanup(fake_validate_staticpage_desc.stop) + fake_validate_form_desc = mock.patch( + "course.validation.validate_form_desc") + self.mock_validate_form_desc = fake_validate_form_desc.start() + self.addCleanup(fake_validate_form_desc.stop) + fake_get_yaml_from_repo = mock.patch( "course.content.get_yaml_from_repo") self.mock_get_yaml_from_repo = fake_get_yaml_from_repo.start() @@ -419,6 +436,10 @@ def test_course_none(self): self.assertSetEqual(expected_validate_staticpage_desc_call_args, args_set) + # make sure validate_form_desc was called with expected args + self.assertEqual(self.mock_validate_form_desc.call_args_list[0][0][1:], + (form1_path, form1_desc)) + # validate_calendar_desc_struct is called self.assertEqual(self.mock_validate_calendar_desc_struct.call_count, 1) diff --git a/tests/test_validation/test_validation_tools.py b/tests/test_validation/test_validation_tools.py index c858b5767..4bc856f67 100644 --- a/tests/test_validation/test_validation_tools.py +++ b/tests/test_validation/test_validation_tools.py @@ -2872,6 +2872,127 @@ def test_fail(self): self.assertIn(expected_error_msg, str(cm.exception)) +class ValidateFormIdTest(ValidationTestMixin, unittest.TestCase): + # test validation.validate_form_id + + def test_success(self): + flow_id = "abc-def" + validation.validate_form_id(vctx, location, flow_id) + flow_id = "abc_def1" + validation.validate_form_id(vctx, location, flow_id) + + def test_fail(self): + expected_error_msg = ( + "invalid form name. Form names may only contain (roman) " + "letters, numbers, dashes and underscores.") + + flow_id = "abc def" + with self.assertRaises(ValidationError) as cm: + validation.validate_form_id(vctx, location, flow_id) + self.assertIn(expected_error_msg, str(cm.exception)) + + flow_id = "abc/def" + with self.assertRaises(ValidationError) as cm: + validation.validate_form_id(vctx, location, flow_id) + self.assertIn(expected_error_msg, str(cm.exception)) + + +class ValidateFormFieldTest(ValidationTestMixin, unittest.TestCase): + # test validation.validate_form_field + + def get_updated_form_field(self, **kwargs): + field_desc = {"id": "my_page_id", + "type": "Text"} + field_desc.update(kwargs) + return dict_to_struct(field_desc) + + def test_success(self): + validation.validate_form_field(vctx, location, + self.get_updated_form_field(id="abc")) + + def test_invalid_form_field_id(self): + expected_error_msg = ( + "invalid form field id. Form field id may only contain (roman) " + "letters, numbers, dashes and underscores.") + with self.assertRaises(ValidationError) as cm: + validation.validate_form_field(vctx, location, + self.get_updated_form_field(id="abc def")) + self.assertIn(expected_error_msg, str(cm.exception)) + + def test_invalid_form_field_type(self): + expected_error_msg = ( + "some_where: form field type 'qwe' not recognized") + with self.assertRaises(ValidationError) as cm: + validation.validate_form_field(vctx, location, + self.get_updated_form_field(type="qwe")) + self.assertIn(expected_error_msg, str(cm.exception)) + + +class ValidateFormTest(ValidationTestMixin, unittest.TestCase): + # test validation.validate_form_desc + + def setUp(self): + super(ValidateFormTest, self).setUp() + patch = mock.patch("course.validation.validate_role") + self.mock_validate_role = patch.start() + self.addCleanup(patch.stop) + + patch = mock.patch("course.validation.validate_form_field") + self.mock_validate_form_field = patch.start() + self.addCleanup(patch.stop) + + def get_updated_form_desc(self, **kwargs): + form_desc = { + "title": "title", + "description": "description", + "type": "flow", + "access_roles": ["ta", "ta2"], + "fields": [ + dict_to_struct({"id": "template_in", "type": "Text"}), + dict_to_struct({"id": "template_out", "type": "Text"}), + ], + } + form_desc.update(kwargs) + return dict_to_struct(form_desc) + + def test_validate_role_called(self): + validation.validate_form_desc(vctx, location, + self.get_updated_form_desc(access_roles=[])) + self.assertEqual(self.mock_validate_role.call_count, 0) + self.assertEqual(self.mock_validate_form_field.call_count, 2) + + validation.validate_form_desc(vctx, location, + self.get_updated_form_desc()) + self.assertEqual(self.mock_validate_role.call_count, 2) + + def test_field_id_unique(self): + expected_error_msg = ("some_where: form field id 'template_in' not unique") + fields = [ + dict_to_struct({"id": "template_in", "type": "Text"}), + dict_to_struct({"id": "template_in", "type": "Text"}), + dict_to_struct({"id": "template_out", "type": "Text"}), + ] + with self.assertRaises(ValidationError) as cm: + validation.validate_form_desc(vctx, location, + self.get_updated_form_desc(fields=fields)) + self.assertIn(expected_error_msg, str(cm.exception)) + + def test_field_required(self): + fields = [ + dict_to_struct({"id": "template_in", "type": "Text"}), + dict_to_struct({"id": "template_out", "type": "Text"}), + ] + + for field_name in ["template_in", "template_out"]: + expected_error_msg = ( + "some_where: required form field id '%s' not found" % field_name) + test_fields = [field for field in fields if field.id != field_name] + with self.assertRaises(ValidationError) as cm: + validation.validate_form_desc(vctx, location, + self.get_updated_form_desc(fields=test_fields)) + self.assertIn(expected_error_msg, str(cm.exception)) + + class ValidateStaticPageNameTest(ValidationTestMixin, unittest.TestCase): # test validation.validate_static_page_name