diff --git a/cms/djangoapps/contentstore/core/course_optimizer_provider.py b/cms/djangoapps/contentstore/core/course_optimizer_provider.py index 2d9714be2060..3389a0f3a367 100644 --- a/cms/djangoapps/contentstore/core/course_optimizer_provider.py +++ b/cms/djangoapps/contentstore/core/course_optimizer_provider.py @@ -76,7 +76,7 @@ def generate_broken_links_descriptor(json_content, request_user): dictionary=xblock_dictionary ) - return _create_dto_from_node_tree_recursive(xblock_node_tree, xblock_dictionary) + return _create_dto_recursive(xblock_node_tree, xblock_dictionary) def _update_node_tree_and_dictionary(block, link, is_locked, node_tree, dictionary): @@ -173,9 +173,10 @@ def _get_node_path(block): } -def _create_dto_from_node_tree_recursive(xblock_node, xblock_dictionary): +def _create_dto_recursive(xblock_node, xblock_dictionary): """ - Recursively build the Data Transfer Object from the node tree and dictionary. + Recursively build the Data Transfer Object by using + the structure from the node tree and data from the dictionary. """ # Exit condition when there are no more child nodes (at block level) if not xblock_node: @@ -185,7 +186,7 @@ def _create_dto_from_node_tree_recursive(xblock_node, xblock_dictionary): xblock_children = [] for xblock_id, node in xblock_node.items(): - child_blocks = _create_dto_from_node_tree_recursive(node, xblock_dictionary) + child_blocks = _create_dto_recursive(node, xblock_dictionary) xblock_data = xblock_dictionary.get(xblock_id, {}) xblock_entry = { diff --git a/cms/djangoapps/contentstore/core/tests/test_course_optimizer_provider.py b/cms/djangoapps/contentstore/core/tests/test_course_optimizer_provider.py index aa78c2fe4856..5470bb05867b 100644 --- a/cms/djangoapps/contentstore/core/tests/test_course_optimizer_provider.py +++ b/cms/djangoapps/contentstore/core/tests/test_course_optimizer_provider.py @@ -10,54 +10,22 @@ generate_broken_links_descriptor, _update_node_tree_and_dictionary, _get_node_path, - _create_dto_from_node_tree_recursive + _create_dto_recursive ) -class TestLinkCheck(CourseTestCase): +class TestLinkCheckProvider(CourseTestCase): """ - Tests for the link check functionality + Tests for functions that generate a json structure of locked and broken links + to send to the frontend. """ def setUp(self): - """Setup for tests""" - global MOCK_TREE - global MOCK_XBLOCK_DICTIONARY + """Setup course blocks for tests""" global MOCK_COURSE global MOCK_SECTION global MOCK_SUBSECTION global MOCK_UNIT global MOCK_BLOCK - MOCK_TREE = { - 'chapter_1': { - 'sequential_1': { - 'vertical_1': { - 'block_1': {} - } - } - } - } - - MOCK_XBLOCK_DICTIONARY = { - 'chapter_1': { - 'display_name': 'Section Name', - 'category': 'chapter' - }, - 'sequential_1': { - 'display_name': 'Subsection Name', - 'category': 'sequential' - }, - 'vertical_1': { - 'display_name': 'Unit Name', - 'category': 'vertical' - }, - 'block_1': { - 'display_name': 'Block Name', - 'url': '/block/1', - 'broken_links': ['broken_link_1', 'broken_link_2'], - 'locked_links': ['locked_link'] - } - } - MOCK_COURSE = Mock() MOCK_SECTION = Mock( location=Mock(block_id='chapter_1'), @@ -80,7 +48,6 @@ def setUp(self): course_id='course-v1:test+course', category='html' ) - # MOCK_BLOCK.location.__str__.return_value = 'block_location_str' MOCK_COURSE.get_parent.return_value = None MOCK_SECTION.get_parent.return_value = MOCK_COURSE MOCK_SUBSECTION.get_parent.return_value = MOCK_SECTION @@ -88,9 +55,32 @@ def setUp(self): MOCK_BLOCK.get_parent.return_value = MOCK_UNIT - def test_update_node_tree_and_dictionary(self): - """Test _update_node_tree_and_dictionary""" - expected_tree = MOCK_TREE + def test_update_node_tree_and_dictionary_returns_node_tree(self): + """ + Verify _update_node_tree_and_dictionary creates a node tree structure + when passed a block level xblock. + """ + expected_tree = { + 'chapter_1': { + 'sequential_1': { + 'vertical_1': { + 'block_1': {} + } + } + } + } + result_tree, result_dictionary = _update_node_tree_and_dictionary( + MOCK_BLOCK, 'example_link', True, {}, {} + ) + + self.assertEqual(expected_tree, result_tree) + + + def test_update_node_tree_and_dictionary_returns_dictionary(self): + """ + Verify _update_node_tree_and_dictionary creates a dictionary of parent xblock entries + when passed a block level xblock. + """ expected_dictionary = { 'chapter_1': { 'display_name': 'Section Name', @@ -111,30 +101,28 @@ def test_update_node_tree_and_dictionary(self): 'locked_links': ['example_link'] } } - result_tree, result_dictionary = _update_node_tree_and_dictionary( MOCK_BLOCK, 'example_link', True, {}, {} ) - self.assertEqual(expected_tree, result_tree) self.assertEqual(expected_dictionary, result_dictionary) - def test_get_node_path(self): - """Tests _get_node_path""" - expected_result = [MOCK_SECTION, MOCK_SUBSECTION, MOCK_UNIT, MOCK_BLOCK] - result = _get_node_path(MOCK_BLOCK) - self.assertEqual(expected_result, result) - - - def test_create_dto_recursive_empty(self): - """Tests _create_dto_from_node_tree_recursive""" - expected = _create_dto_from_node_tree_recursive({}, {}) + def test_create_dto_recursive_returns_for_empty_node(self): + """ + Test _create_dto_recursive behavior at the end of recursion. + Function should return None when given empty node tree and empty dictionary. + """ + expected = _create_dto_recursive({}, {}) self.assertEqual(None, expected) - def test_create_dto_recursive_leaf_node(self): - """Tests _create_dto_from_node_tree_recursive""" + def test_create_dto_recursive_returns_for_leaf_node(self): + """ + Test _create_dto_recursive behavior at the step before the end of recursion. + When evaluating a leaf node in the node tree, the function should return broken links + and locked links data from the leaf node. + """ expected_result = { 'blocks': [ { @@ -146,15 +134,40 @@ def test_create_dto_recursive_leaf_node(self): } ] } - expected = _create_dto_from_node_tree_recursive( - MOCK_TREE['chapter_1']['sequential_1']['vertical_1'], - MOCK_XBLOCK_DICTIONARY - ) + + mock_node_tree = { + 'block_1': {} + } + mock_dictionary = { + 'chapter_1': { + 'display_name': 'Section Name', + 'category': 'chapter' + }, + 'sequential_1': { + 'display_name': 'Subsection Name', + 'category': 'sequential' + }, + 'vertical_1': { + 'display_name': 'Unit Name', + 'category': 'vertical' + }, + 'block_1': { + 'display_name': 'Block Name', + 'url': '/block/1', + 'broken_links': ['broken_link_1', 'broken_link_2'], + 'locked_links': ['locked_link'] + } + } + expected = _create_dto_recursive(mock_node_tree, mock_dictionary) self.assertEqual(expected_result, expected) - def test_create_dto_recursive_full_tree(self): - """Tests _create_dto_from_node_tree_recursive""" + def test_create_dto_recursive_returns_for_full_tree(self): + """ + Test _create_dto_recursive behavior when recursing many times. + When evaluating a fully mocked node tree and dictionary, the function should return + a full json DTO prepared for frontend. + """ expected_result = { 'sections': [ { @@ -185,6 +198,36 @@ def test_create_dto_recursive_full_tree(self): ] } - expected = _create_dto_from_node_tree_recursive(MOCK_TREE, MOCK_XBLOCK_DICTIONARY) + mock_node_tree = { + 'chapter_1': { + 'sequential_1': { + 'vertical_1': { + 'block_1': {} + } + } + } + } + mock_dictionary = { + 'chapter_1': { + 'display_name': 'Section Name', + 'category': 'chapter' + }, + 'sequential_1': { + 'display_name': 'Subsection Name', + 'category': 'sequential' + }, + 'vertical_1': { + 'display_name': 'Unit Name', + 'category': 'vertical' + }, + 'block_1': { + 'display_name': 'Block Name', + 'url': '/block/1', + 'broken_links': ['broken_link_1', 'broken_link_2'], + 'locked_links': ['locked_link'] + } + } + expected = _create_dto_recursive(mock_node_tree, mock_dictionary) + self.assertEqual(expected_result, expected) \ No newline at end of file