def load_block_as_anonymous_user(location): """ Load a block as anonymous user. This uses a few internal courseware methods to retrieve the descriptor and bind an AnonymousUser to it, in a similar fashion as a `noauth` XBlock handler. """ # pylint: disable=import-error,import-outside-toplevel from django.contrib.auth.models import AnonymousUser from xmodule.modulestore.django import modulestore from lms.djangoapps.courseware.module_render import get_module_for_descriptor_internal # Retrieve descriptor from modulestore descriptor = modulestore().get_item(location) # Load block, attaching it to AnonymousUser get_module_for_descriptor_internal( user=AnonymousUser(), descriptor=descriptor, student_data=None, course_id=location.course_key, track_function=None, xqueue_callback_url_prefix="", request_token="", ) return descriptor
def load_block_as_anonymous_user(location): """ Load a block as anonymous user. This uses a few internal courseware methods to retrieve the descriptor and bind an AnonymousUser to it, in a similar fashion as a `noauth` XBlock handler. """ # pylint: disable=import-error,import-outside-toplevel from crum import impersonate from django.contrib.auth.models import AnonymousUser from xmodule.modulestore.django import modulestore from lms.djangoapps.courseware.module_render import get_module_for_descriptor_internal # Retrieve descriptor from modulestore descriptor = modulestore().get_item(location) # ensure `crum.get_current_user` returns AnonymousUser. It returns None when outside # of request scope which causes error during block loading. user = AnonymousUser() with impersonate(user): # Load block, attaching it to AnonymousUser get_module_for_descriptor_internal( user=user, descriptor=descriptor, student_data=None, course_id=location.course_key, track_function=None, request_token="", ) return descriptor
def test_embed_mfe_in_course(self): """ Test that the xblock embeds the MFE UI when the flag is enabled """ discussion_xblock = get_module_for_descriptor_internal( user=self.user, descriptor=self.discussion, student_data=mock.Mock(name='student_data'), course_id=self.course.id, track_function=mock.Mock(name='track_function'), request_token='request_token', ) fragment = discussion_xblock.render('student_view') html = fragment.content self.assertInHTML( """ <iframe id='discussions-mfe-tab-embed' title='Discussions' src='http://test.url/edX/toy/2012_Fall/topics/test_discussion_xblock_id' /> """, html, )
def _get_module_instance_for_task(course_id, student, module_descriptor, xmodule_instance_args=None, grade_bucket_type=None, course=None): """ Fetches a StudentModule instance for a given `course_id`, `student` object, and `module_descriptor`. `xmodule_instance_args` is used to provide information for creating a track function and an XQueue callback. These are passed, along with `grade_bucket_type`, to get_module_for_descriptor_internal, which sidesteps the need for a Request object when instantiating an xmodule instance. """ # reconstitute the problem's corresponding XModule: field_data_cache = FieldDataCache.cache_for_descriptor_descendents( course_id, student, module_descriptor) student_data = KvsFieldData(DjangoKeyValueStore(field_data_cache)) # get request-related tracking information from args passthrough, and supplement with task-specific # information: request_info = xmodule_instance_args.get( 'request_info', {}) if xmodule_instance_args is not None else {} task_info = { "student": student.username, "task_id": _get_task_id_from_xmodule_args(xmodule_instance_args) } def make_track_function(): ''' Make a tracking function that logs what happened. For insertion into ModuleSystem, and used by CapaModule, which will provide the event_type (as string) and event (as dict) as arguments. The request_info and task_info (and page) are provided here. ''' return lambda event_type, event: task_track( request_info, task_info, event_type, event, page='x_module_task') xqueue_callback_url_prefix = xmodule_instance_args.get('xqueue_callback_url_prefix', '') \ if xmodule_instance_args is not None else '' return get_module_for_descriptor_internal( user=student, descriptor=module_descriptor, student_data=student_data, course_id=course_id, track_function=make_track_function(), xqueue_callback_url_prefix=xqueue_callback_url_prefix, grade_bucket_type=grade_bucket_type, # This module isn't being used for front-end rendering request_token=None, # pass in a loaded course for override enabling course=course)
def test_discussion_render_successfully_with_orphan_parent( self, default_store): """ Test that discussion xblock render successfully if discussion xblock is child of an orphan. """ with self.store.default_store(default_store): orphan_sequential = self.store.create_item(self.user.id, self.course.id, 'sequential') vertical = self.store.create_child( self.user.id, orphan_sequential.location, 'vertical', block_id=self.course.location.block_id) discussion = self.store.create_child( self.user.id, vertical.location, 'discussion', block_id=self.course.location.block_id) discussion = self.store.get_item(discussion.location) root = self.get_root(discussion) # Assert that orphan sequential is root of the discussion xblock. self.assertEqual(orphan_sequential.location.block_type, root.location.block_type) self.assertEqual(orphan_sequential.location.block_id, root.location.block_id) # Get xblock bound to a user and a descriptor. discussion_xblock = get_module_for_descriptor_internal( user=self.user, descriptor=discussion, student_data=mock.Mock(name='student_data'), course_id=self.course.id, track_function=mock.Mock(name='track_function'), xqueue_callback_url_prefix=mock.Mock( name='xqueue_callback_url_prefix'), request_token='request_token', ) fragment = discussion_xblock.render('student_view') html = fragment.content self.assertIsInstance(discussion_xblock, DiscussionXBlock) self.assertIn('data-user-create-comment="false"', html) self.assertIn('data-user-create-subcomment="false"', html)
def test_permissions_query_load(self): """ Tests that the permissions queries are cached when rendering numerous discussion XBlocks. """ user = UserFactory() course = ToyCourseFactory() course_key = course.id course_usage_key = self.store.make_course_usage_key(course_key) discussions = [] for counter in range(5): discussion_id = f'test_discussion_{counter}' discussions.append( ItemFactory.create( parent_location=course_usage_key, category='discussion', discussion_id=discussion_id, discussion_category='Category discussion', discussion_target='Target Discussion', )) # 7 queries are required to do first discussion xblock render: # * split_modulestore_django_splitmodulestorecourseindex x2 # * waffle_utils_wafflecourseoverridemodel # * waffle_utils_waffleorgoverridemodel # * waffle_flag # * django_comment_client_role # * lms_xblock_xblockasidesconfig num_queries = 7 for discussion in discussions: discussion_xblock = get_module_for_descriptor_internal( user=user, descriptor=discussion, student_data=mock.Mock(name='student_data'), course_id=course.id, track_function=mock.Mock(name='track_function'), request_token='request_token', ) with self.assertNumQueries(num_queries): fragment = discussion_xblock.render('student_view') # Permissions are cached, so only 1 query required for subsequent renders # to check the waffle flag num_queries = 1 html = fragment.content assert 'data-user-create-comment="false"' in html assert 'data-user-create-subcomment="false"' in html
def test_html_with_user(self): """ Test rendered DiscussionXBlock permissions. """ discussion_xblock = get_module_for_descriptor_internal( user=self.user, descriptor=self.discussion, student_data=mock.Mock(name='student_data'), course_id=self.course.id, track_function=mock.Mock(name='track_function'), request_token='request_token', ) fragment = discussion_xblock.render('student_view') html = fragment.content assert 'data-user-create-comment="false"' in html assert 'data-user-create-subcomment="false"' in html
def test_permissions_query_load(self): """ Tests that the permissions queries are cached when rendering numerous discussion XBlocks. """ user = UserFactory() course = ToyCourseFactory() course_key = course.id course_usage_key = self.store.make_course_usage_key(course_key) discussions = [] for counter in range(5): discussion_id = 'test_discussion_{}'.format(counter) discussions.append( ItemFactory.create( parent_location=course_usage_key, category='discussion', discussion_id=discussion_id, discussion_category='Category discussion', discussion_target='Target Discussion', )) # 3 queries are required to do first discussion xblock render: # * django_comment_client_role # * django_comment_client_permission # * lms_xblock_xblockasidesconfig num_queries = 2 for discussion in discussions: discussion_xblock = get_module_for_descriptor_internal( user=user, descriptor=discussion, student_data=mock.Mock(name='student_data'), course_id=course.id, track_function=mock.Mock(name='track_function'), xqueue_callback_url_prefix=mock.Mock( name='xqueue_callback_url_prefix'), request_token='request_token', ) with self.assertNumQueries(num_queries): fragment = discussion_xblock.render('student_view') # Permissions are cached, so no queries required for subsequent renders num_queries = 0 html = fragment.content self.assertIn('data-user-create-comment="false"', html) self.assertIn('data-user-create-subcomment="false"', html)