Skip to content

Commit

Permalink
feat: course_optimizer_provider tests
Browse files Browse the repository at this point in the history
  • Loading branch information
rayzhou-bit committed Jan 15, 2025
1 parent ebee1d9 commit 4bf67c4
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 147 deletions.
21 changes: 17 additions & 4 deletions cms/djangoapps/contentstore/core/course_optimizer_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ def generate_broken_links_descriptor(json_content, request_user):
"""
Returns a Data Transfer Object for frontend given a list of broken links.
json_content contains a list of [block_id, link, is_locked]
is_locked is true if the link is a studio link and returns 403 on request
** Example json_content structure **
Note: is_locked is true if the link is a studio link and returns 403
[
['block_id_1', 'link_1', is_locked],
['block_id_1', 'link_2', is_locked],
['block_id_2', 'link_3', is_locked],
...
]
** Example DTO structure **
{
Expand Down Expand Up @@ -100,9 +106,16 @@ def _update_node_tree_and_dictionary(block, link, is_locked, node_tree, dictiona
** Example dictionary structure **
{
'xblock_id: {
'display_name': 'xblock name'
'category': 'html'
'display_name': 'xblock name',
'category': 'chapter'
},
'html_block_id': {
'display_name': 'xblock name',
'category': 'chapter',
'url': 'url_1',
'locked_links': [...],
'broken_links': [...]
}
...,
}
"""
Expand Down
235 changes: 92 additions & 143 deletions cms/djangoapps/contentstore/core/tests/test_course_optimizer_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ class TestLinkCheck(CourseTestCase):
Tests for the link check functionality
"""
def setUp(self):
"""Setup for tests"""
global MOCK_TREE
global MOCK_XBLOCK_DICTIONARY
global MOCK_COURSE
global MOCK_SECTION
global MOCK_SUBSECTION
global MOCK_UNIT
global MOCK_BLOCK

MOCK_TREE = {
'chapter_1': {
'sequential_1': {
Expand All @@ -29,39 +36,110 @@ def setUp(self):
}
}
}

MOCK_XBLOCK_DICTIONARY = {
'chapter_1': {
'display_name': 'Chapter 1',
'display_name': 'Section Name',
'category': 'chapter'
},
'sequential_1': {
'display_name': 'Sequential 1',
'display_name': 'Subsection Name',
'category': 'sequential'
},
'vertical_1': {
'display_name': 'Vertical 1',
'display_name': 'Unit Name',
'category': 'vertical'
},
'block_1': {
'display_name': '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'),
display_name='Section Name',
category='chapter'
)
MOCK_SUBSECTION = Mock(
location=Mock(block_id='sequential_1'),
display_name='Subsection Name',
category='sequential'
)
MOCK_UNIT = Mock(
location=Mock(block_id='vertical_1'),
display_name='Unit Name',
category='vertical'
)
MOCK_BLOCK = Mock(
location=Mock(block_id='block_1'),
display_name='Block Name',
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
MOCK_UNIT.get_parent.return_value = MOCK_SUBSECTION
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
expected_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',
'category': 'html',
'url': f'/course/{MOCK_BLOCK.course_id}/editor/html/{MOCK_BLOCK.location}',
'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_recursive_empty(self):
def test_create_dto_recursive_empty(self):
"""Tests _create_dto_from_node_tree_recursive"""
expected = _create_dto_from_node_tree_recursive({}, {})
self.assertEqual(None, expected)


def test_recursive_leaf_node(self):
def test_create_dto_recursive_leaf_node(self):
"""Tests _create_dto_from_node_tree_recursive"""
expected_result = {
'blocks': [
{
'id': 'block_1',
'displayName': 'Block 1',
'displayName': 'Block Name',
'url': '/block/1',
'brokenLinks': ['broken_link_1', 'broken_link_2'],
'lockedLinks': ['locked_link']
Expand All @@ -75,24 +153,25 @@ def test_recursive_leaf_node(self):
self.assertEqual(expected_result, expected)


def test_recursive_full_tree(self):
def test_create_dto_recursive_full_tree(self):
"""Tests _create_dto_from_node_tree_recursive"""
expected_result = {
'sections': [
{
'id': 'chapter_1',
'displayName': 'Chapter 1',
'displayName': 'Section Name',
'subsections': [
{
'id': 'sequential_1',
'displayName': 'Sequential 1',
'displayName': 'Subsection Name',
'units': [
{
'id': 'vertical_1',
'displayName': 'Vertical 1',
'displayName': 'Unit Name',
'blocks': [
{
'id': 'block_1',
'displayName': 'Block 1',
'displayName': 'Block Name',
'url': '/block/1',
'brokenLinks': ['broken_link_1', 'broken_link_2'],
'lockedLinks': ['locked_link']
Expand All @@ -108,134 +187,4 @@ def test_recursive_full_tree(self):

expected = _create_dto_from_node_tree_recursive(MOCK_TREE, MOCK_XBLOCK_DICTIONARY)
self.assertEqual(expected_result, expected)


def test_get_node_path(self):
mock_course = Mock()
mock_section = Mock(
location=Mock(block_id='section_id'),
display_name='Section Name'
)
mock_subsection = Mock(
location=Mock(block_id='subsection_id'),
display_name='Subsection Name'
)
mock_unit = Mock(
location=Mock(block_id='unit_id'),
display_name='Unit Name'
)
mock_block = Mock(
course_id='course-v1:test+course+2024',
location=Mock(block_id='block_id'),
display_name='Block Name',
category='html'
)
mock_course.get_parent.return_value = None
mock_section.get_parent.return_value = mock_course
mock_subsection.get_parent.return_value = mock_section
mock_unit.get_parent.return_value = mock_subsection
mock_block.get_parent.return_value = mock_unit

expected_result = [mock_course, mock_section, mock_subsection, mock_unit, mock_block]

result = _get_node_path(mock_unit)
self.assertEqual(expected_result, result)


# @patch('cms.djangoapps.contentstore.core.course_optimizer_provider._create_dto_from_node_tree_recursive')
@patch('cms.djangoapps.contentstore.core.course_optimizer_provider._update_node_tree_and_dictionary')
@patch('cms.djangoapps.contentstore.core.course_optimizer_provider.get_xblock')
@patch('cms.djangoapps.contentstore.core.course_optimizer_provider.usage_key_with_run')
def test_generate_broken_links_descriptor_returns_correct_result(
self,
mock_usage_key_with_run,
mock_get_xblock,
mock_update_node_tree_and_dictionary,
# mock_create_dto_from_node_tree_recursive
):
"""
Test generate_broken_links_descriptor to return expected dto
"""
# Mock data
mock_course = Mock()
mock_section = Mock(
location=Mock(block_id='section_id'),
display_name='Section Name'
)
mock_section.get_parent.side_effect = mock_course
mock_subsection = Mock(
location=Mock(block_id='subsection_id'),
display_name='Subsection Name'
)
mock_subsection.get_parent.side_effect = mock_section
mock_unit = Mock(
location=Mock(block_id='unit_id'),
display_name='Unit Name'
)
mock_unit.get_parent.side_effect = mock_subsection
mock_block = Mock(
course_id='course-v1:test+course+2024',
location=Mock(block_id='block_id'),
display_name='Block Name'
)
mock_block.get_parent.side_effect = mock_unit
mock_block.category = 'html'
# mock_block.get_parent.side_effect = [
# Mock(location=Mock(block_id="unit_id"), display_name="Unit Name"),
# Mock(location=Mock(block_id="subsection_id"), display_name="Subsection Name"),
# Mock(location=Mock(block_id="section_id"), display_name="Section Name"),
# None,
# ]

# Mock functions
mock_usage_key_with_run.return_value = "mock_usage_key"
mock_get_xblock.return_value = mock_block
mock_update_node_tree_and_dictionary.return_value = Mock()
# mock_create_dto_from_node_tree_recursive.return_value = 'test'

# Mock input
mock_json_content = [
["block_id", "http://example.com/broken-link1", False],
["block_id", "http://example.com/locked-link1", True],
["block_id", "http://example.com/broken-link2", False],
]
request_user = Mock()

# Expected output
expected_result = {
'sections': [
{
'id': 'section_id',
'displayName': 'Section Name',
'subsections': [
{
'id': 'subsection_id',
'displayName': 'Subsection Name',
'units': [
{
'id': 'unit_id',
'displayName': 'Unit Name',
'blocks': [
{
'id': 'block_id',
'displayName': 'Block Name',
'url': '/course/course-v1:test+course+2024/editor/html/mock_usage_key',
'brokenLinks': [
"http://example.com/broken-link1",
"http://example.com/broken-link2",
],
'lockedLinks': ["http://example.com/broken-link1"],
},
]
}
]
}
]
}
]
}

# Call the function
result = generate_broken_links_descriptor(mock_json_content, request_user)

self.assertEqual(result, expected_result)

0 comments on commit 4bf67c4

Please sign in to comment.