From 648fbf85cb837bb06f0f9ac92d8093c1d9177b8b Mon Sep 17 00:00:00 2001 From: Muhammad Tayayb Tahir Qureshi Date: Thu, 21 Nov 2024 15:02:38 +0500 Subject: [PATCH] fix: fix tests --- xblocks_contrib/lti/lti_2_util.py | 2 +- xblocks_contrib/lti/tests/__init__.py | 61 ------------------- xblocks_contrib/lti/tests/helpers.py | 63 +++++++++++++++++++- xblocks_contrib/lti/tests/test_lti_2_unit.py | 4 +- xblocks_contrib/lti/tests/test_lti_unit.py | 24 ++++---- 5 files changed, 75 insertions(+), 79 deletions(-) diff --git a/xblocks_contrib/lti/lti_2_util.py b/xblocks_contrib/lti/lti_2_util.py index f7d05a9..70823e8 100644 --- a/xblocks_contrib/lti/lti_2_util.py +++ b/xblocks_contrib/lti/lti_2_util.py @@ -153,7 +153,7 @@ def parse_lti_2_0_handler_suffix(self, suffix): log.info(f"[LTI]: {msg}") raise LTIError(msg) - def _round_away_from_zero(number, digits=0): + def _round_away_from_zero(self, number, digits=0): """ Round numbers using the 'away from zero' strategy as opposed to the 'Banker's rounding strategy.' The strategy refers to how we round when diff --git a/xblocks_contrib/lti/tests/__init__.py b/xblocks_contrib/lti/tests/__init__.py index 524024d..e69de29 100644 --- a/xblocks_contrib/lti/tests/__init__.py +++ b/xblocks_contrib/lti/tests/__init__.py @@ -1,61 +0,0 @@ -from opaque_keys.edx.keys import CourseKey - - -def get_test_system( - course_id=CourseKey.from_string('/'.join(['org', 'course', 'run'])), - user=None, - user_is_staff=False, - user_location=None, - render_template=None, - add_get_block_overrides=False -): - """ - Construct a test DescriptorSystem instance. - - By default, the descriptor system's render_template() method simply returns the repr of the - context it is passed. You can override this by passing in a different render_template argument. - """ - - id_manager = CourseLocationManager(course_id) - - descriptor_system = get_test_descriptor_system(id_reader=id_manager, id_generator=id_manager) - - if not user: - user = Mock(name='get_test_system.user', is_staff=False) - if not user_location: - user_location = Mock(name='get_test_system.user_location') - user_service = StubUserService( - user=user, - anonymous_user_id='student', - deprecated_anonymous_user_id='student', - user_is_staff=user_is_staff, - user_role='student', - request_country_code=user_location, - ) - - mako_service = StubMakoService(render_template=render_template) - - replace_url_service = StubReplaceURLService() - - def get_block(block): - """Mocks module_system get_block function""" - - prepare_block_runtime(block.runtime, add_overrides=add_get_block_overrides) - block.runtime.get_block_for_descriptor = get_block - block.bind_for_student(user.id) - - return block - - services = { - 'user': user_service, - 'mako': mako_service, - 'replace_urls': replace_url_service, - 'cache': CacheService(DoNothingCache()), - 'field-data': DictFieldData({}), - 'sandbox': SandboxService(contentstore, course_id), - } - - descriptor_system.get_block_for_descriptor = get_block # lint-amnesty, pylint: disable=attribute-defined-outside-init - descriptor_system._services.update(services) # lint-amnesty, pylint: disable=protected-access - - return descriptor_system \ No newline at end of file diff --git a/xblocks_contrib/lti/tests/helpers.py b/xblocks_contrib/lti/tests/helpers.py index 11745b3..d9d8dca 100644 --- a/xblocks_contrib/lti/tests/helpers.py +++ b/xblocks_contrib/lti/tests/helpers.py @@ -3,11 +3,13 @@ """ import datetime -import pytest import re -from path import Path as path +from unittest.mock import Mock +from opaque_keys.edx.keys import CourseKey from xblock.fields import JSONField from xblock.reference.user_service import UserService, XBlockUser +from xblock.reference.plugins import NO_CACHE_VALUE +from xblock.runtime import Runtime TIMEDELTA_REGEX = re.compile(r'^((?P\d+?) day(?:s?))?(\s)?((?P\d+?) hour(?:s?))?(\s)?((?P\d+?) minute(?:s)?)?(\s)?((?P\d+?) second(?:s)?)?$') # lint-amnesty, pylint: disable=line-too-long @@ -110,3 +112,60 @@ def get_user_by_anonymous_id(self, uid=None): # pylint: disable=unused-argument Return the original user passed into the service. """ return self.user + + +class MockRuntime(Runtime): + """A mock implementation of the Runtime class for testing purposes.""" + + def __init__(self, anonymous_student_id, services=None): + # id_reader and id_generator are required by Runtime. + super().__init__(id_reader=lambda: None, id_generator=lambda: None, services=services) + self.anonymous_student_id = anonymous_student_id + + def handler_url(self, block, handler_name, suffix="", thirdparty=False): + return f"/mock_url/{handler_name}" + + def local_resource_url(self, block, resource): + return f"/mock_resource_url/{resource}" + + def resource_url(self, resource): + return f"/mock_resource/{resource}" + + def publish(self, block, event_type, event_data): + pass + + +def get_test_system( + course_id=CourseKey.from_string("/".join(["org", "course", "run"])), + user=None, + user_is_staff=False, + user_location=None, +): + """Construct a minimal test system for the LTIBlockTest.""" + # course_id = course_id or CourseKey.from_string("org/course/run") + # user = user or Mock(id="student", is_staff=user_is_staff) + + if not user: + user = Mock(name='get_test_system.user', is_staff=False) + if not user_location: + user_location = Mock(name='get_test_system.user_location') + user_service = StubUserService( + user=user, + anonymous_user_id='student', + deprecated_anonymous_user_id='student', + user_is_staff=user_is_staff, + user_role='student', + request_country_code=user_location, + ) + runtime = MockRuntime( + anonymous_student_id="student", + services={ + "user": user_service, + } + ) + + # Add necessary mocks + runtime.publish = Mock(name="publish") + runtime._services["rebind_user"] = Mock(name="rebind_user") + + return runtime diff --git a/xblocks_contrib/lti/tests/test_lti_2_unit.py b/xblocks_contrib/lti/tests/test_lti_2_unit.py index 7ede8ce..b45e667 100644 --- a/xblocks_contrib/lti/tests/test_lti_2_unit.py +++ b/xblocks_contrib/lti/tests/test_lti_2_unit.py @@ -11,9 +11,7 @@ from xblocks_contrib.lti.lti_2_util import LTIError from xblocks_contrib.lti.lti import LTIBlock -from .helpers import StubUserService - -from . import get_test_system +from .helpers import StubUserService, get_test_system class LTI20RESTResultServiceTest(unittest.TestCase): diff --git a/xblocks_contrib/lti/tests/test_lti_unit.py b/xblocks_contrib/lti/tests/test_lti_unit.py index 95c5d69..4ac3a8f 100644 --- a/xblocks_contrib/lti/tests/test_lti_unit.py +++ b/xblocks_contrib/lti/tests/test_lti_unit.py @@ -20,10 +20,10 @@ from xblocks_contrib.lti.lti_2_util import LTIError -from xblocks_contrib.lti.lti import LTIBlock, ATTR_KEY_ANONYMOUS_USER_ID -from .helpers import StubUserService, Timedelta +from xblocks_contrib.lti.lti import LTIBlock +from .helpers import StubUserService, Timedelta, get_test_system -from . import get_test_system +ATTR_KEY_ANONYMOUS_USER_ID = 'edx-platform.anonymous_user_id' @override_settings(LMS_BASE="edx.org") @@ -124,7 +124,7 @@ def get_response_values(self, response): } @patch( - 'xmodule.lti_block.LTIBlock.get_client_key_secret', + 'xblocks_contrib.lti.lti.LTIBlock.get_client_key_secret', return_value=('test_client_key', 'test_client_secret') ) def test_authorization_header_not_present(self, _get_key_secret): @@ -148,7 +148,7 @@ def test_authorization_header_not_present(self, _get_key_secret): self.assertDictEqual(expected_response, real_response) @patch( - 'xmodule.lti_block.LTIBlock.get_client_key_secret', + 'xblocks_contrib.lti.lti.LTIBlock.get_client_key_secret', return_value=('test_client_key', 'test_client_secret') ) def test_authorization_header_empty(self, _get_key_secret): @@ -310,7 +310,7 @@ def mock_handler_url(block, handler_name, **kwargs): # pylint: disable=unused-a assert real_outcome_service_url == (mock_url_prefix + test_service_name) def test_resource_link_id(self): - with patch('xmodule.lti_block.LTIBlock.location', new_callable=PropertyMock): + with patch('xblocks_contrib.lti.lti.LTIBlock.location', new_callable=PropertyMock): self.xblock.location.html_id = lambda: 'i4x-2-3-lti-31de800015cf4afb973356dbe81496df' expected_resource_link_id = str(parse.quote(self.unquoted_resource_link_id)) real_resource_link_id = self.xblock.get_resource_link_id() @@ -375,9 +375,9 @@ def test_bad_client_key_secret(self): with pytest.raises(LTIError): self.xblock.get_client_key_secret() - @patch('xmodule.lti_block.signature.verify_hmac_sha1', Mock(return_value=True)) + @patch('xblocks_contrib.lti.lti.signature.verify_hmac_sha1', Mock(return_value=True)) @patch( - 'xmodule.lti_block.LTIBlock.get_client_key_secret', + 'xblocks_contrib.lti.lti.LTIBlock.get_client_key_secret', Mock(return_value=('test_client_key', 'test_client_secret')) ) def test_successful_verify_oauth_body_sign(self): @@ -386,8 +386,8 @@ def test_successful_verify_oauth_body_sign(self): """ self.xblock.verify_oauth_body_sign(self.get_signed_grade_mock_request()) - @patch('xmodule.lti_block.LTIBlock.get_outcome_service_url', Mock(return_value='https://testurl/')) - @patch('xmodule.lti_block.LTIBlock.get_client_key_secret', + @patch('xblocks_contrib.lti.lti.LTIBlock.get_outcome_service_url', Mock(return_value='https://testurl/')) + @patch('xblocks_contrib.lti.lti.LTIBlock.get_client_key_secret', Mock(return_value=('__consumer_key__', '__lti_secret__'))) def test_failed_verify_oauth_body_sign_proxy_mangle_url(self): """ @@ -457,9 +457,9 @@ def test_parse_grade_xml_body(self): assert self.defaults['grade'] == grade assert self.defaults['action'] == action - @patch('xmodule.lti_block.signature.verify_hmac_sha1', Mock(return_value=False)) + @patch('xblocks_contrib.lti.lti.signature.verify_hmac_sha1', Mock(return_value=False)) @patch( - 'xmodule.lti_block.LTIBlock.get_client_key_secret', + 'xblocks_contrib.lti.lti.LTIBlock.get_client_key_secret', Mock(return_value=('test_client_key', 'test_client_secret')) ) def test_failed_verify_oauth_body_sign(self):