def _get_anonymous_id(self, course_id, xblock_class): location = course_id.make_usage_key('dummy_category', 'dummy_name') descriptor = Mock( spec=xblock_class, _field_data=Mock(spec=FieldData), location=location, static_asset_path=None, runtime=Mock(spec=Runtime, resources_fs=None, mixologist=Mock(_mixins=())), scope_ids=Mock(spec=ScopeIds), ) # Use the xblock_class's bind_for_student method descriptor.bind_for_student = partial(xblock_class.bind_for_student, descriptor) if hasattr(xblock_class, 'module_class'): descriptor.module_class = xblock_class.module_class return render.get_module_for_descriptor_internal( self.user, descriptor, Mock(spec=FieldDataCache), course_id, Mock(), # Track Function Mock(), # XQueue Callback Url Prefix ).xmodule_runtime.anonymous_student_id
def _get_anonymous_id(self, course_id, xblock_class): location = course_id.make_usage_key("dummy_category", "dummy_name") descriptor = Mock( spec=xblock_class, _field_data=Mock(spec=FieldData), location=location, static_asset_path=None, runtime=Mock(spec=Runtime, resources_fs=None, mixologist=Mock(_mixins=())), scope_ids=Mock(spec=ScopeIds), ) # Use the xblock_class's bind_for_student method descriptor.bind_for_student = partial(xblock_class.bind_for_student, descriptor) if hasattr(xblock_class, "module_class"): descriptor.module_class = xblock_class.module_class return render.get_module_for_descriptor_internal( user=self.user, descriptor=descriptor, field_data_cache=Mock(spec=FieldDataCache), course_id=course_id, track_function=Mock(), # Track Function xqueue_callback_url_prefix=Mock(), # XQueue Callback Url Prefix request_token="request_token", ).xmodule_runtime.anonymous_student_id
def _get_anonymous_id(self, course_id, xblock_class): location = Location('dummy_org', 'dummy_course', 'dummy_category', 'dummy_name') descriptor = Mock( spec=xblock_class, _field_data=Mock(spec=FieldData), location=location, static_asset_path=None, runtime=Mock( spec=Runtime, resources_fs=None, mixologist=Mock(_mixins=()) ), scope_ids=Mock(spec=ScopeIds), ) # Use the xblock_class's bind_for_student method descriptor.bind_for_student = partial(xblock_class.bind_for_student, descriptor) if hasattr(xblock_class, 'module_class'): descriptor.module_class = xblock_class.module_class return render.get_module_for_descriptor_internal( self.user, descriptor, Mock(spec=FieldDataCache), course_id, Mock(), # Track Function Mock(), # XQueue Callback Url Prefix ).xmodule_runtime.anonymous_student_id
def _get_anonymous_id(self, course_id, xblock_class): location = course_id.make_usage_key('dummy_category', 'dummy_name') descriptor = Mock( spec=xblock_class, _field_data=Mock(spec=FieldData), location=location, static_asset_path=None, _runtime=Mock( spec=Runtime, resources_fs=None, mixologist=Mock(_mixins=(), name='mixologist'), name='runtime', ), scope_ids=Mock(spec=ScopeIds), name='descriptor' ) descriptor.runtime = CombinedSystem(descriptor._runtime, None) # pylint: disable=protected-access # Use the xblock_class's bind_for_student method descriptor.bind_for_student = partial(xblock_class.bind_for_student, descriptor) if hasattr(xblock_class, 'module_class'): descriptor.module_class = xblock_class.module_class return render.get_module_for_descriptor_internal( user=self.user, descriptor=descriptor, field_data_cache=Mock(spec=FieldDataCache, name='field_data_cache'), course_id=course_id, track_function=Mock(name='track_function'), # Track Function xqueue_callback_url_prefix=Mock(name='xqueue_callback_url_prefix'), # XQueue Callback Url Prefix request_token='request_token', ).xmodule_runtime.anonymous_student_id
def _get_module_instance_for_task(course_id, student, module_descriptor, xmodule_instance_args=None, grade_bucket_type=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) # 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(student, module_descriptor, field_data_cache, course_id, make_track_function(), xqueue_callback_url_prefix, grade_bucket_type=grade_bucket_type)
def _get_module_instance_for_task(course_id, student, module_descriptor, xmodule_instance_args=None, grade_bucket_type=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) # 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(student, module_descriptor, field_data_cache, course_id, make_track_function(), xqueue_callback_url_prefix, grade_bucket_type=grade_bucket_type)
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_discussion_render_successfully_with_orphan_parent( self, default_store): """ Test that discussion module render successfully if discussion module is child of an orphan. """ user = UserFactory.create() store = modulestore() with store.default_store(default_store): course = store.create_course('testX', 'orphan', '123X', user.id) orphan_sequential = store.create_item(self.user.id, course.id, 'sequential') vertical = store.create_child(user.id, orphan_sequential.location, 'vertical', block_id=course.location.block_id) discussion = store.create_child(user.id, vertical.location, 'discussion', block_id=course.location.block_id) discussion = store.get_item(discussion.location) root = self.get_root(discussion) # Assert that orphan sequential is root of the discussion module. self.assertEqual(orphan_sequential.location.block_type, root.location.block_type) self.assertEqual(orphan_sequential.location.block_id, root.location.block_id) # Get module system bound to a user and a descriptor. discussion_module = get_module_for_descriptor_internal( user=user, descriptor=discussion, student_data=Mock(name='student_data'), course_id=course.id, track_function=Mock(name='track_function'), xqueue_callback_url_prefix=Mock( name='xqueue_callback_url_prefix'), request_token='request_token', ) fragment = discussion_module.render('student_view') html = fragment.content self.assertIsInstance(discussion_module._xmodule, DiscussionModule) # pylint: disable=protected-access self.assertIn('data-user-create-comment="false"', html) self.assertIn('data-user-create-subcomment="false"', html)
def create_module(descriptor): '''creates an XModule instance given a descriptor''' with manual_transaction(): field_data_cache = FieldDataCache([descriptor], course.id, student) # don't need tracking/xqueue but we have to pass something return get_module_for_descriptor_internal( student, descriptor, field_data_cache, course.id, track_function=noop_track_function, # dummy xqueue_callback_url_prefix='', # dummy request_token='') # dummy
def test_discussion_render_successfully_with_orphan_parent(self, default_store): """ Test that discussion module render successfully if discussion module is child of an orphan. """ user = UserFactory.create() store = modulestore() with store.default_store(default_store): course = store.create_course('testX', 'orphan', '123X', user.id) orphan_sequential = store.create_item(self.user.id, course.id, 'sequential') vertical = store.create_child( user.id, orphan_sequential.location, 'vertical', block_id=course.location.block_id ) discussion = store.create_child( user.id, vertical.location, 'discussion', block_id=course.location.block_id ) discussion = store.get_item(discussion.location) root = self.get_root(discussion) # Assert that orphan sequential is root of the discussion module. self.assertEqual(orphan_sequential.location.block_type, root.location.block_type) self.assertEqual(orphan_sequential.location.block_id, root.location.block_id) # Get module system bound to a user and a descriptor. discussion_module = get_module_for_descriptor_internal( user=user, descriptor=discussion, student_data=Mock(name='student_data'), course_id=course.id, track_function=Mock(name='track_function'), xqueue_callback_url_prefix=Mock(name='xqueue_callback_url_prefix'), request_token='request_token', ) fragment = discussion_module.render('student_view') html = fragment.content self.assertIsInstance(discussion_module._xmodule, DiscussionModule) # pylint: disable=protected-access self.assertIn('data-user-create-comment="false"', html) self.assertIn('data-user-create-subcomment="false"', html)
def test_html_with_user(self): discussion = get_module_for_descriptor_internal( user=self.users[0], descriptor=self.item_descriptor, student_data=Mock(name='student_data'), course_id=self.course.id, track_function=Mock(name='track_function'), xqueue_callback_url_prefix=Mock(name='xqueue_callback_url_prefix'), request_token='request_token', ) fragment = discussion.render('student_view') html = fragment.content self.assertIn('data-user-create-comment="false"', html) self.assertIn('data-user-create-subcomment="false"', html)
def test_html_with_user(self): discussion = get_module_for_descriptor_internal( user=self.users[0], descriptor=self.item_descriptor, student_data=Mock(name='student_data'), course_id=self.course.id, track_function=Mock(name='track_function'), xqueue_callback_url_prefix=Mock(name='xqueue_callback_url_prefix'), request_token='request_token', ) fragment = discussion.render('student_view') html = fragment.content 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 = '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', )) # 2 queries are required to do first discussion xblock render: # * django_comment_client_role # * lms_xblock_xblockasidesconfig # If the query for roles returned a non-empty result set, there would be # an additional query against django_comment_client_permission, but there # are no roles associated with this test. 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)
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.create() course = ToyCourseFactory.create() 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 = 3 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)
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'), 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.assertIn('data-user-create-comment="false"', html) self.assertIn('data-user-create-subcomment="false"', html)