Skip to content

Commit

Permalink
test: add tests for known and unknown user
Browse files Browse the repository at this point in the history
  • Loading branch information
asadali145 committed Oct 31, 2024
1 parent d9a27b6 commit 9ed41b0
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 153 deletions.
148 changes: 148 additions & 0 deletions lms/djangoapps/course_blocks/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# pylint: disable=attribute-defined-outside-init
"""
Tests for course_blocks API
"""

from unittest.mock import Mock, patch

import ddt
from django.http.request import HttpRequest

from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.course_blocks.api import get_course_blocks
from lms.djangoapps.course_blocks.transformers.tests.helpers import CourseStructureTestCase
from lms.djangoapps.course_blocks.transformers.tests.test_user_partitions import UserPartitionTestMixin
from lms.djangoapps.courseware.block_render import make_track_function, prepare_runtime_for_user
from openedx.core.djangoapps.content.block_structure.transformers import BlockStructureTransformers
from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort
from xmodule.modulestore.django import modulestore


def get_block_side_effect(block_locator, user_known):
"""
Side effect for `CachingDescriptorSystem.get_block`
"""
store = modulestore()
course = store.get_course(block_locator.course_key)
block = store.get_item(block_locator)
runtime = block.runtime
user = UserFactory.create()
user.known = user_known

prepare_runtime_for_user(
user=user,
student_data=Mock(),
runtime=runtime,
course_id=block_locator.course_key,
track_function=make_track_function(HttpRequest()),
request_token=Mock(),
course=course,
)
return block.runtime.get_block_for_descriptor(block)


def get_block_side_effect_for_known_user(self, *args, **kwargs):
"""
Side effect for known user test.
"""
return get_block_side_effect(self, True)


def get_block_side_effect_for_unknown_user(self, *args, **kwargs):
"""
Side effect for unknown user test.
"""
return get_block_side_effect(self, False)



@ddt.ddt
class TestGetCourseBlocks(UserPartitionTestMixin, CourseStructureTestCase):
"""
Tests `get_course_blocks` API
"""

def setup_partitions_and_course(self):
"""
Setup course structure.
"""
# Set up user partitions and groups.
self.setup_groups_partitions(active=True, num_groups=1)
self.user_partition = self.user_partitions[0]

# Build course.
self.course_hierarchy = self.get_course_hierarchy()
self.blocks = self.build_course(self.course_hierarchy)
self.course = self.blocks['course']

# Set up cohorts.
self.setup_cohorts(self.course)

def get_course_hierarchy(self):
"""
Returns a course hierarchy to test with.
"""
# course
# / \
# / \
# A[0, 1, 2, 3] B
# |
# |
# O

return [
{
'org': 'UserPartitionTransformer',
'course': 'UP101F',
'run': 'test_run',
'user_partitions': [self.user_partition],
'#type': 'course',
'#ref': 'course',
'#children': [
{
'#type': 'vertical',
'#ref': 'A',
'metadata': {'group_access': {self.user_partition.id: [0]}},
},
{'#type': 'vertical', '#ref': 'B'},
],
},
{
'#type': 'vertical',
'#ref': 'O',
'#parents': ['B'],
},
]

@ddt.data(
(1, ('course', 'B', 'O'), True),
(1, ('course', 'A', 'B', 'O'), False),
)
@ddt.unpack
def test_get_course_blocks(self, group_id, expected_blocks, user_known):
"""
Tests that `get_course_blocks` returns blocks without access checks for unknown users.
Access checks are done through the transformers and through Runtime get_block_for_descriptor. Due
to the runtime limitations during the tests, the Runtime access checks are not performed as
get_block_for_descriptor is never called and Block is returned by CachingDescriptorSystem.get_block.
In this test, we mock the CachingDescriptorSystem.get_block and check block access for known and unknown users.
For known users, it performs the Runtime access checks through get_block_for_descriptor. For unknown, it
skips the access checks.
"""
self.setup_partitions_and_course()
if group_id:
cohort = self.partition_cohorts[self.user_partition.id - 1][group_id - 1]
add_user_to_cohort(cohort, self.user.username)

side_effect = get_block_side_effect_for_known_user if user_known else get_block_side_effect_for_unknown_user
with patch('xmodule.modulestore.split_mongo.split.CachingDescriptorSystem.get_block', side_effect=side_effect):
block_structure = get_course_blocks(
self.user,
self.course.location,
BlockStructureTransformers([]),
)
self.assertSetEqual(
set(block_structure.get_block_keys()),
self.get_block_key_set(self.blocks, *expected_blocks)
)
154 changes: 1 addition & 153 deletions openedx/core/djangoapps/content/block_structure/tests/test_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@

import ddt
import pytest
from django.core.cache import cache
from django.test import TestCase
from edx_toggles.toggles.testutils import override_waffle_switch

from common.djangoapps.student.tests.factories import CourseEnrollmentFactory
from lms.djangoapps.course_blocks.transformers.tests.helpers import CourseStructureTestCase
from lms.djangoapps.course_blocks.transformers.tests.test_user_partitions import UserPartitionTestMixin
from openedx.core.djangoapps.content.block_structure.api import get_block_structure_manager
from openedx.core.djangoapps.course_groups.cohorts import add_user_to_cohort

from ..block_structure import BlockStructureBlockData
from ..config import STORAGE_BACKING_FOR_CACHE
from ..exceptions import UsageKeyNotInBlockStructure
Expand Down Expand Up @@ -227,150 +222,3 @@ def test_clear(self):
self.bs_manager.clear()
self.collect_and_verify(expect_modulestore_called=True, expect_cache_updated=True)
assert TestTransformer1.collect_call_count == 2


@ddt.ddt
class TestBlockStructureManagerGetCollected(UserPartitionTestMixin, CourseStructureTestCase):
"""
Tests `BlockStructureManager.get_collected`
"""

def setup_partitions_and_course(self):
"""
Setup course structure and create user.
"""
# Set up user partitions and groups.
self.setup_groups_partitions(active=True)
self.user_partition = self.user_partitions[0]

# Build course.
self.course_hierarchy = self.get_course_hierarchy()
self.blocks = self.build_course(self.course_hierarchy)
self.course = self.blocks['course']

# Enroll user in course.
CourseEnrollmentFactory.create(
user=self.user, course_id=self.course.id, is_active=True
)

# Set up cohorts.
self.setup_cohorts(self.course)

def get_course_hierarchy(self):
"""
Returns a course hierarchy to test with.
"""
# course
# / \
# / \
# A[1, 2, 3] B
# / | \ |
# / | \ |
# / | \ |
# C[1, 2] D[2, 3] E /
# / | \ | / \ /
# / | \ | / \ /
# / | \ | / \ /
# F G[1] H[2] I J K[4] /
# / \ / / \ /
# / \ / / \ /
# / \ / / \/
# L[1, 2] M[1, 2, 3] N O
#
return [
{
'org': 'UserPartitionTransformer',
'course': 'UP101F',
'run': 'test_run',
'user_partitions': [self.user_partition],
'#type': 'course',
'#ref': 'course',
'#children': [
{
'#type': 'vertical',
'#ref': 'A',
'metadata': {'group_access': {self.user_partition.id: [0, 1, 2, 3]}},
},
{'#type': 'vertical', '#ref': 'B'},
],
},
{
'#type': 'vertical',
'#ref': 'C',
'#parents': ['A'],
'metadata': {'group_access': {self.user_partition.id: [1, 2]}},
'#children': [
{'#type': 'vertical', '#ref': 'F'},
{
'#type': 'vertical',
'#ref': 'G',
'metadata': {'group_access': {self.user_partition.id: [1]}},
},
{
'#type': 'vertical',
'#ref': 'H',
'metadata': {'group_access': {self.user_partition.id: [2]}},
},
],
},
{
'#type': 'vertical',
'#ref': 'D',
'#parents': ['A'],
'metadata': {'group_access': {self.user_partition.id: [2, 3]}},
'#children': [{'#type': 'vertical', '#ref': 'I'}],
},
{
'#type': 'vertical',
'#ref': 'E',
'#parents': ['A'],
'#children': [{'#type': 'vertical', '#ref': 'J'}],
},
{
'#type': 'vertical',
'#ref': 'K',
'#parents': ['E'],
'metadata': {'group_access': {self.user_partition.id: [4, 51]}},
'#children': [{'#type': 'vertical', '#ref': 'N'}],
},
{
'#type': 'vertical',
'#ref': 'L',
'#parents': ['G'],
'metadata': {'group_access': {self.user_partition.id: [1, 2]}},
},
{
'#type': 'vertical',
'#ref': 'M',
'#parents': ['G', 'H'],
'metadata': {'group_access': {self.user_partition.id: [1, 2, 3]}},
},
{
'#type': 'vertical',
'#ref': 'O',
'#parents': ['K', 'B'],
},
]

@ddt.data(
(None, ('course', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O')),
(1, ('course', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O')),
(2, ('course', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O')),
(3, ('course', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O')),
(4, ('course', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O')),
)
@ddt.unpack
def test_get_collected(self, group_id, expected_blocks):
"""
Test that `BlockStructureManager.get_collected` returns all course blocks regardless of the user group.
"""
self.setup_partitions_and_course()
if group_id:
cohort = self.partition_cohorts[self.user_partition.id - 1][group_id - 1]
add_user_to_cohort(cohort, self.user.username)

trans_block_structure = get_block_structure_manager(self.course.location.course_key).get_collected(self.user)
self.assertSetEqual(
set(trans_block_structure.get_block_keys()),
self.get_block_key_set(self.blocks, *expected_blocks)
)

0 comments on commit 9ed41b0

Please sign in to comment.