From 39563c327ccbfcd79ecec431c3345ab4bba4cfd3 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Fri, 14 Feb 2014 06:33:53 -0500 Subject: [PATCH 1/5] Make staff view work w/ pure xblocks (that only have a descriptor system) --- common/djangoapps/xmodule_modifiers.py | 4 ++-- common/lib/xmodule/xmodule/x_module.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/common/djangoapps/xmodule_modifiers.py b/common/djangoapps/xmodule_modifiers.py index fc95891063..21fb55c460 100644 --- a/common/djangoapps/xmodule_modifiers.py +++ b/common/djangoapps/xmodule_modifiers.py @@ -173,9 +173,9 @@ def add_staff_debug_info(user, block, view, frag, context): # pylint: disable=u histogram = None render_histogram = False - if settings.FEATURES.get('ENABLE_LMS_MIGRATION'): + if settings.FEATURES.get('ENABLE_LMS_MIGRATION') and hasattr(block.runtime, 'filestore'): [filepath, filename] = getattr(block, 'xml_attributes', {}).get('filename', ['', None]) - osfs = block.system.filestore + osfs = block.runtime.filestore if filename is not None and osfs.exists(filename): # if original, unmangled filename exists then use it (github # doesn't like symlinks) diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index a136edcdaf..e452536fae 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -141,6 +141,10 @@ class XModuleMixin(XBlockMixin): default=None ) + @property + def system(self): + return self.runtime + @property def course_id(self): return self.runtime.course_id @@ -400,7 +404,6 @@ class XModule(XModuleMixin, HTMLSnippet, XBlock): # pylint: disable=abstract-me self.descriptor = descriptor super(XModule, self).__init__(*args, **kwargs) self._loaded_children = None - self.system = self.runtime self.runtime.xmodule_instance = self def __unicode__(self): @@ -634,7 +637,6 @@ class XModuleDescriptor(XModuleMixin, HTMLSnippet, ResourceTemplates, XBlock): XModuleDescriptor.__init__ takes the same arguments as xblock.core:XBlock.__init__ """ super(XModuleDescriptor, self).__init__(*args, **kwargs) - self.system = self.runtime # update_version is the version which last updated this xblock v prev being the penultimate updater # leaving off original_version since it complicates creation w/o any obv value yet and is computable # by following previous until None From 9126777ed79d7f1a123cb28e2c20f926afb03a2c Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Fri, 14 Feb 2014 06:44:10 -0500 Subject: [PATCH 2/5] Add test of local_resource_url in AcidBlock --- .../contentstore/tests/test_crud.py | 5 +- .../contentstore/views/component.py | 4 +- cms/djangoapps/contentstore/views/item.py | 4 +- cms/djangoapps/contentstore/views/preview.py | 6 +++ .../contentstore/views/session_kv_store.py | 1 + cms/djangoapps/contentstore/views/xblock.py | 33 +++++++++++++ cms/envs/common.py | 1 - cms/lib/xblock/runtime.py | 9 ++++ cms/urls.py | 3 ++ .../xmodule/modulestore/split_mongo/split.py | 2 +- common/lib/xmodule/xmodule/tests/__init__.py | 3 ++ common/lib/xmodule/xmodule/x_module.py | 48 +++++++++++++++---- common/test/acceptance/pages/xblock/acid.py | 7 +++ common/test/acceptance/tests/test_lms.py | 1 + common/test/acceptance/tests/test_studio.py | 2 + lms/djangoapps/courseware/module_render.py | 18 +++++++ lms/lib/xblock/runtime.py | 9 ++++ lms/urls.py | 3 ++ requirements/edx/github.txt | 2 +- 19 files changed, 146 insertions(+), 15 deletions(-) create mode 100644 cms/djangoapps/contentstore/views/xblock.py diff --git a/cms/djangoapps/contentstore/tests/test_crud.py b/cms/djangoapps/contentstore/tests/test_crud.py index 290b90e4bc..078cc7eefb 100644 --- a/cms/djangoapps/contentstore/tests/test_crud.py +++ b/cms/djangoapps/contentstore/tests/test_crud.py @@ -1,4 +1,6 @@ import unittest +from django.conf import settings + from xmodule import templates from xmodule.modulestore.tests import persistent_factories from xmodule.course_module import CourseDescriptor @@ -9,7 +11,6 @@ from xmodule.modulestore.locator import CourseLocator, BlockUsageLocator, LocalI from xmodule.modulestore.exceptions import ItemNotFoundError from xmodule.html_module import HtmlDescriptor from xmodule.modulestore import inheritance -from xmodule.x_module import prefer_xmodules from xblock.core import XBlock @@ -252,7 +253,7 @@ class TemplateTests(unittest.TestCase): class_ = XBlock.load_class( json_data.get('category', json_data.get('location', {}).get('category')), default_class, - select=prefer_xmodules + select=settings.XBLOCK_SELECT_FUNCTION ) usage_id = json_data.get('_id', None) if not '_inherited_settings' in json_data and parent_xblock is not None: diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index 7b8eb5b252..840a41d0ca 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import json import logging from collections import defaultdict @@ -147,7 +149,7 @@ def _load_mixed_class(category): """ Load an XBlock by category name, and apply all defined mixins """ - component_class = XBlock.load_class(category, select=prefer_xmodules) + component_class = XBlock.load_class(category, select=settings.XBLOCK_SELECT_FUNCTION) mixologist = Mixologist(settings.XBLOCK_MIXINS) return mixologist.mix(component_class) diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index 80548a27a7..16c2bfe545 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -1,4 +1,5 @@ """Views for items (modules).""" +from __future__ import absolute_import import hashlib import logging @@ -37,7 +38,7 @@ from .helpers import _xmodule_recurse from contentstore.views.preview import get_preview_fragment from edxmako.shortcuts import render_to_string from models.settings.course_grading import CourseGradingModel -from cms.lib.xblock.runtime import handler_url +from cms.lib.xblock.runtime import handler_url, local_resource_url __all__ = ['orphan_handler', 'xblock_handler', 'xblock_view_handler'] @@ -50,6 +51,7 @@ CREATE_IF_NOT_FOUND = ['course_info'] # monkey-patch the x_module library. # TODO: Remove this code when Runtimes are no longer created by modulestores xmodule.x_module.descriptor_global_handler_url = handler_url +xmodule.x_module.descriptor_global_local_resource_url = local_resource_url def hash_resource(resource): diff --git a/cms/djangoapps/contentstore/views/preview.py b/cms/djangoapps/contentstore/views/preview.py index 33951a6089..f0a4d73e34 100644 --- a/cms/djangoapps/contentstore/views/preview.py +++ b/cms/djangoapps/contentstore/views/preview.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import + import logging import hashlib from functools import partial @@ -21,6 +23,7 @@ from xblock.fragment import Fragment from lms.lib.xblock.field_data import LmsFieldData from lms.lib.xblock.runtime import quote_slashes, unquote_slashes +from cms.lib.xblock.runtime import local_resource_url from util.sandboxing import can_execute_unsafe_code @@ -87,6 +90,9 @@ class PreviewModuleSystem(ModuleSystem): # pylint: disable=abstract-method 'suffix': suffix, }) + '?' + query + def local_resource_url(self, block, uri): + return local_resource_url(block, uri) + def _preview_module_system(request, descriptor): """ diff --git a/cms/djangoapps/contentstore/views/session_kv_store.py b/cms/djangoapps/contentstore/views/session_kv_store.py index ddee2c1dbc..b04aa7b194 100644 --- a/cms/djangoapps/contentstore/views/session_kv_store.py +++ b/cms/djangoapps/contentstore/views/session_kv_store.py @@ -1,6 +1,7 @@ """ An :class:`~xblock.runtime.KeyValueStore` that stores data in the django session """ +from __future__ import absolute_import from xblock.runtime import KeyValueStore diff --git a/cms/djangoapps/contentstore/views/xblock.py b/cms/djangoapps/contentstore/views/xblock.py new file mode 100644 index 0000000000..f45df73fd3 --- /dev/null +++ b/cms/djangoapps/contentstore/views/xblock.py @@ -0,0 +1,33 @@ +""" +Views dedicated to rendering xblocks. +""" +from __future__ import absolute_import + +import logging +import mimetypes + +from xblock.core import XBlock + +from django.conf import settings +from django.http import Http404, HttpResponse + + +log = logging.getLogger(__name__) + + +def xblock_resource(request, block_type, uri): # pylint: disable=unused-argument + """ + Return a package resource for the specified XBlock. + """ + try: + xblock_class = XBlock.load_class(block_type, settings.XBLOCK_SELECT_FUNCTION) + content = xblock_class.open_local_resource(uri) + except IOError: + log.info('Failed to load xblock resource', exc_info=True) + raise Http404 + except Exception: # pylint: disable-msg=broad-except + log.error('Failed to load xblock resource', exc_info=True) + raise Http404 + + mimetype, _ = mimetypes.guess_type(uri) + return HttpResponse(content, mimetype=mimetype) diff --git a/cms/envs/common.py b/cms/envs/common.py index 23b7de10a5..c9a5506489 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -91,7 +91,6 @@ GITHUB_REPO_ROOT = ENV_ROOT / "data" sys.path.append(REPO_ROOT) sys.path.append(PROJECT_ROOT / 'djangoapps') -sys.path.append(PROJECT_ROOT / 'lib') sys.path.append(COMMON_ROOT / 'djangoapps') sys.path.append(COMMON_ROOT / 'lib') diff --git a/cms/lib/xblock/runtime.py b/cms/lib/xblock/runtime.py index e0e2491028..f40cfdc328 100644 --- a/cms/lib/xblock/runtime.py +++ b/cms/lib/xblock/runtime.py @@ -26,3 +26,12 @@ def handler_url(block, handler_name, suffix='', query='', thirdparty=False): return url + +def local_resource_url(block, uri): + """ + local_resource_url for Studio + """ + return reverse('xblock_resource_url', kwargs={ + 'block_type': block.scope_ids.block_type, + 'uri': uri, + }) diff --git a/cms/urls.py b/cms/urls.py index 8ddfc2e2f7..fb2a2d2d22 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -22,6 +22,9 @@ urlpatterns = patterns('', # nopep8 url(r'^xblock/(?P.*?)/handler/(?P[^/]*)(?:/(?P.*))?$', 'contentstore.views.component_handler', name='component_handler'), + url(r'^xblock/resource/(?P[^/]*)/(?P.*)$', + 'contentstore.views.xblock.xblock_resource', name='xblock_resource_url'), + # temporary landing page for a course url(r'^edge/(?P[^/]+)/(?P[^/]+)/course/(?P[^/]+)$', 'contentstore.views.landing', name='landing'), diff --git a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py index 6f0cba3318..4837ad1252 100644 --- a/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py +++ b/common/lib/xmodule/xmodule/modulestore/split_mongo/split.py @@ -1496,7 +1496,7 @@ class SplitMongoModuleStore(ModuleStoreWriteBase): """ if fields is None: return {} - cls = self.mixologist.mix(XBlock.load_class(category, select=prefer_xmodules)) + cls = self.mixologist.mix(XBlock.load_class(category, select=self.xblock_select)) result = collections.defaultdict(dict) for field_name, value in fields.iteritems(): field = getattr(cls, field_name) diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py index 4dce45af91..7a537df95d 100644 --- a/common/lib/xmodule/xmodule/tests/__init__.py +++ b/common/lib/xmodule/xmodule/tests/__init__.py @@ -47,6 +47,9 @@ class TestModuleSystem(ModuleSystem): # pylint: disable=abstract-method def handler_url(self, block, handler, suffix='', query='', thirdparty=False): return str(block.scope_ids.usage_id) + '/' + handler + '/' + suffix + '?' + query + def local_resource_url(self, block, uri): + return 'resource/' + str(block.scope_ids.block_type) + '/' + uri + def get_test_system(course_id=''): """ diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index e452536fae..6d9ada7314 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -143,6 +143,9 @@ class XModuleMixin(XBlockMixin): @property def system(self): + """ + Return the XBlock runtime (backwards compatibility alias provided for XModules). + """ return self.runtime @property @@ -893,8 +896,21 @@ class ConfigurableFragmentWrapper(object): # pylint: disable=abstract-method # This function exists to give applications (LMS/CMS) a place to monkey-patch until # we can refactor modulestore to split out the FieldData half of its interface from # the Runtime part of its interface. This function matches the Runtime.handler_url interface -def descriptor_global_handler_url(block, handler_name, suffix='', query='', thirdparty=False): - raise NotImplementedError("Applications must monkey-patch this function before using handler-urls for studio_view") +def descriptor_global_handler_url(block, handler_name, suffix='', query='', thirdparty=False): # pylint: disable=invalid-name, unused-argument + """ + See :meth:`xblock.runtime.Runtime.handler_url`. + """ + raise NotImplementedError("Applications must monkey-patch this function before using handler_url for studio_view") + + +# This function exists to give applications (LMS/CMS) a place to monkey-patch until +# we can refactor modulestore to split out the FieldData half of its interface from +# the Runtime part of its interface. This function matches the Runtime.local_resource_url interface +def descriptor_global_local_resource_url(block, uri): # pylint: disable=invalid-name, unused-argument + """ + See :meth:`xblock.runtime.Runtime.local_resource_url`. + """ + raise NotImplementedError("Applications must monkey-patch this function before using local_resource_url for studio_view") class DescriptorSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable=abstract-method @@ -943,6 +959,8 @@ class DescriptorSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable get_policy: a function that takes a usage id and returns a dict of policy to apply. + local_resource_url: an implementation of :meth:`xblock.runtime.Runtime.local_resource_url` + """ super(DescriptorSystem, self).__init__(**kwargs) @@ -1010,13 +1028,30 @@ class DescriptorSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable # global function that the application can override. return descriptor_global_handler_url(block, handler_name, suffix, query, thirdparty) - def resource_url(self, resource): - raise NotImplementedError("edX Platform doesn't currently implement XBlock resource urls") - def local_resource_url(self, block, uri): + """ + See :meth:`xblock.runtime.Runtime:local_resource_url` for documentation. + """ + xmodule_runtime = getattr(block, 'xmodule_runtime', None) + if xmodule_runtime is not None: + return xmodule_runtime.local_resource_url(block, uri) + else: + # Currently, Modulestore is responsible for instantiating DescriptorSystems + # This means that LMS/CMS don't have a way to define a subclass of DescriptorSystem + # that implements the correct local_resource_url. So, for now, instead, we will reference a + # global function that the application can override. + return descriptor_global_local_resource_url(block, uri) + + def resource_url(self, resource): + """ + See :meth:`xblock.runtime.Runtime:resource_url` for documentation. + """ raise NotImplementedError("edX Platform doesn't currently implement XBlock resource urls") def publish(self, block, event): + """ + See :meth:`xblock.runtime.Runtime:publish` for documentation. + """ raise NotImplementedError("edX Platform doesn't currently implement XBlock publish") def add_block_as_child_node(self, block, node): @@ -1182,9 +1217,6 @@ class ModuleSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable=abs def resource_url(self, resource): raise NotImplementedError("edX Platform doesn't currently implement XBlock resource urls") - def local_resource_url(self, block, uri): - raise NotImplementedError("edX Platform doesn't currently implement XBlock resource urls") - def publish(self, block, event): pass diff --git a/common/test/acceptance/pages/xblock/acid.py b/common/test/acceptance/pages/xblock/acid.py index 4aa54e458c..90794feb44 100644 --- a/common/test/acceptance/pages/xblock/acid.py +++ b/common/test/acceptance/pages/xblock/acid.py @@ -61,6 +61,13 @@ class AcidView(PageObject): self.test_passed('.child-values-match') ]) + @property + def resource_url_passed(self): + """ + Whether the resource-url test passed in this view of the :class:`.AcidBlock`. + """ + return self.test_passed('.local-resource-test') + def scope_passed(self, scope): return all( self.test_passed('.scope-storage-test.scope-{} {}'.format(scope, test)) diff --git a/common/test/acceptance/tests/test_lms.py b/common/test/acceptance/tests/test_lms.py index 2f0946f4c2..d65c098f1c 100644 --- a/common/test/acceptance/tests/test_lms.py +++ b/common/test/acceptance/tests/test_lms.py @@ -371,6 +371,7 @@ class XBlockAcidBase(UniqueCourseTest): self.assertTrue(acid_block.init_fn_passed) self.assertTrue(acid_block.doc_ready_passed) self.assertTrue(acid_block.child_tests_passed) + self.assertTrue(acid_block.resource_url_passed) self.assertTrue(acid_block.scope_passed('user_state')) diff --git a/common/test/acceptance/tests/test_studio.py b/common/test/acceptance/tests/test_studio.py index 17bfc0a75c..742436e853 100644 --- a/common/test/acceptance/tests/test_studio.py +++ b/common/test/acceptance/tests/test_studio.py @@ -159,6 +159,7 @@ class XBlockAcidBase(WebAppTest): self.assertTrue(acid_block.init_fn_passed) self.assertTrue(acid_block.doc_ready_passed) self.assertTrue(acid_block.child_tests_passed) + self.assertTrue(acid_block.resource_url_passed) self.assertTrue(acid_block.scope_passed('user_state')) def test_acid_block_editor(self): @@ -175,6 +176,7 @@ class XBlockAcidBase(WebAppTest): self.assertTrue(acid_block.init_fn_passed) self.assertTrue(acid_block.doc_ready_passed) self.assertTrue(acid_block.child_tests_passed) + self.assertTrue(acid_block.resource_url_passed) self.assertTrue(acid_block.scope_passed('content')) self.assertTrue(acid_block.scope_passed('settings')) diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index f636ccea7c..2f55322feb 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -1,5 +1,6 @@ import json import logging +import mimetypes import static_replace @@ -545,6 +546,23 @@ def handle_xblock_callback(request, course_id, usage_id, handler, suffix=None): return _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, request.user) +def xblock_resource(request, block_type, uri): # pylint: disable=unused-argument + """ + Return a package resource for the specified XBlock. + """ + try: + xblock_class = XBlock.load_class(block_type, select=settings.XBLOCK_SELECT_FUNCTION) + content = xblock_class.open_local_resource(uri) + except IOError: + log.info('Failed to load xblock resource', exc_info=True) + raise Http404 + except Exception: # pylint: disable-msg=broad-except + log.error('Failed to load xblock resource', exc_info=True) + raise Http404 + mimetype, _ = mimetypes.guess_type(uri) + return HttpResponse(content, mimetype=mimetype) + + def _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, user): """ Invoke an XBlock handler, either authenticated or not. diff --git a/lms/lib/xblock/runtime.py b/lms/lib/xblock/runtime.py index a339a0a98a..c905e098d4 100644 --- a/lms/lib/xblock/runtime.py +++ b/lms/lib/xblock/runtime.py @@ -99,6 +99,15 @@ class LmsHandlerUrls(object): return url + def local_resource_url(self, block, uri): + """ + local_resource_url for Studio + """ + return reverse('xblock_resource_url', kwargs={ + 'block_type': block.scope_ids.block_type, + 'uri': uri, + }) + class LmsModuleSystem(LmsHandlerUrls, ModuleSystem): # pylint: disable=abstract-method """ diff --git a/lms/urls.py b/lms/urls.py index 634aec78c3..9f66578156 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -190,6 +190,9 @@ if settings.COURSEWARE_ENABLED: url(r'^courses/(?P[^/]+/[^/]+/[^/]+)/xblock/(?P[^/]*)/handler_noauth/(?P[^/]*)(?:/(?P.*))?$', 'courseware.module_render.handle_xblock_callback_noauth', name='xblock_handler_noauth'), + url(r'xblock/resource/(?P[^/]+)/(?P.*)$', + 'courseware.module_render.xblock_resource', + name='xblock_resource_url'), # Software Licenses diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index c8cb2c4897..2dd8385498 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -23,4 +23,4 @@ -e git+https://github.com/edx/event-tracking.git@f0211d702d#egg=event-tracking -e git+https://github.com/edx/bok-choy.git@62de7b576a08f36cde5b030c52bccb1a2f3f8df1#egg=bok_choy -e git+https://github.com/edx-solutions/django-splash.git@15bf143b15714e22fc451ff1b0f8a7a2a9483172#egg=django-splash --e git+https://github.com/edx/acid-block.git@9c832513f0c01f79227bea894fba11c66fe4c08c#egg=acid-xblock +-e git+https://github.com/edx/acid-block.git@ce4c09615055a3cc14e39689e881c3422ff3162c#egg=acid-xblock From 35fbc15edb24c44a078bd1594660bbdbe92da477 Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Fri, 14 Feb 2014 06:44:22 -0500 Subject: [PATCH 3/5] Add tests of more scopes in student_view --- common/test/acceptance/tests/test_lms.py | 3 +++ common/test/acceptance/tests/test_studio.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/common/test/acceptance/tests/test_lms.py b/common/test/acceptance/tests/test_lms.py index d65c098f1c..34e7c71605 100644 --- a/common/test/acceptance/tests/test_lms.py +++ b/common/test/acceptance/tests/test_lms.py @@ -373,6 +373,9 @@ class XBlockAcidBase(UniqueCourseTest): self.assertTrue(acid_block.child_tests_passed) self.assertTrue(acid_block.resource_url_passed) self.assertTrue(acid_block.scope_passed('user_state')) + self.assertTrue(acid_block.scope_passed('user_state_summary')) + self.assertTrue(acid_block.scope_passed('preferences')) + self.assertTrue(acid_block.scope_passed('user_info')) class XBlockAcidNoChildTest(XBlockAcidBase): diff --git a/common/test/acceptance/tests/test_studio.py b/common/test/acceptance/tests/test_studio.py index 742436e853..b79c145b15 100644 --- a/common/test/acceptance/tests/test_studio.py +++ b/common/test/acceptance/tests/test_studio.py @@ -161,6 +161,9 @@ class XBlockAcidBase(WebAppTest): self.assertTrue(acid_block.child_tests_passed) self.assertTrue(acid_block.resource_url_passed) self.assertTrue(acid_block.scope_passed('user_state')) + self.assertTrue(acid_block.scope_passed('user_state_summary')) + self.assertTrue(acid_block.scope_passed('preferences')) + self.assertTrue(acid_block.scope_passed('user_info')) def test_acid_block_editor(self): """ From ae34c3fe9f493d53b7911ccd874af7a88874ed0e Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Mon, 24 Feb 2014 12:39:45 -0500 Subject: [PATCH 4/5] Mark xblock initialization status using css class (in part to make testing easier) --- common/static/coffee/src/xblock/core.coffee | 1 + common/test/acceptance/pages/xblock/acid.py | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/common/static/coffee/src/xblock/core.coffee b/common/static/coffee/src/xblock/core.coffee index 72768cac63..e305fc80fa 100644 --- a/common/static/coffee/src/xblock/core.coffee +++ b/common/static/coffee/src/xblock/core.coffee @@ -22,6 +22,7 @@ $element.trigger("xblock-initialized") $element.data("initialized", true) + $element.addClass("xblock-initialized") block initializeBlocks: (element) -> diff --git a/common/test/acceptance/pages/xblock/acid.py b/common/test/acceptance/pages/xblock/acid.py index 90794feb44..64064c2e1e 100644 --- a/common/test/acceptance/pages/xblock/acid.py +++ b/common/test/acceptance/pages/xblock/acid.py @@ -25,10 +25,7 @@ class AcidView(PageObject): self.context_selector = context_selector def is_browser_on_page(self): - return ( - self.is_css_present('{} .acid-block'.format(self.context_selector)) and - self.browser.evaluate_script("$({!r}).data('initialized')".format(self.context_selector)) - ) + return self.is_css_present('{}.xblock-initialized .acid-block'.format(self.context_selector)) def test_passed(self, test_selector): """ From c72d410083ac41cacf085cd366bbfa7bf3556d8c Mon Sep 17 00:00:00 2001 From: Calen Pennington Date: Mon, 24 Feb 2014 13:36:59 -0500 Subject: [PATCH 5/5] Remove doc-ready tests, which were flaky --- common/test/acceptance/pages/xblock/acid.py | 7 ------- common/test/acceptance/tests/test_lms.py | 1 - common/test/acceptance/tests/test_studio.py | 2 -- requirements/edx/github.txt | 2 +- 4 files changed, 1 insertion(+), 11 deletions(-) diff --git a/common/test/acceptance/pages/xblock/acid.py b/common/test/acceptance/pages/xblock/acid.py index 64064c2e1e..a3ae6d4885 100644 --- a/common/test/acceptance/pages/xblock/acid.py +++ b/common/test/acceptance/pages/xblock/acid.py @@ -41,13 +41,6 @@ class AcidView(PageObject): """ return self.test_passed('.js-init-run') - @property - def doc_ready_passed(self): - """ - Whether the document-ready test passed in this view of the :class:`.AcidBlock`. - """ - return self.test_passed('.document-ready-run') - @property def child_tests_passed(self): """ diff --git a/common/test/acceptance/tests/test_lms.py b/common/test/acceptance/tests/test_lms.py index 34e7c71605..621d1ac988 100644 --- a/common/test/acceptance/tests/test_lms.py +++ b/common/test/acceptance/tests/test_lms.py @@ -369,7 +369,6 @@ class XBlockAcidBase(UniqueCourseTest): acid_block = AcidView(self.browser, '.xblock-student_view[data-block-type=acid]') self.assertTrue(acid_block.init_fn_passed) - self.assertTrue(acid_block.doc_ready_passed) self.assertTrue(acid_block.child_tests_passed) self.assertTrue(acid_block.resource_url_passed) self.assertTrue(acid_block.scope_passed('user_state')) diff --git a/common/test/acceptance/tests/test_studio.py b/common/test/acceptance/tests/test_studio.py index b79c145b15..f190abd0b4 100644 --- a/common/test/acceptance/tests/test_studio.py +++ b/common/test/acceptance/tests/test_studio.py @@ -157,7 +157,6 @@ class XBlockAcidBase(WebAppTest): acid_block = AcidView(self.browser, unit.components[0].preview_selector) self.assertTrue(acid_block.init_fn_passed) - self.assertTrue(acid_block.doc_ready_passed) self.assertTrue(acid_block.child_tests_passed) self.assertTrue(acid_block.resource_url_passed) self.assertTrue(acid_block.scope_passed('user_state')) @@ -177,7 +176,6 @@ class XBlockAcidBase(WebAppTest): acid_block = AcidView(self.browser, unit.components[0].edit().editor_selector) self.assertTrue(acid_block.init_fn_passed) - self.assertTrue(acid_block.doc_ready_passed) self.assertTrue(acid_block.child_tests_passed) self.assertTrue(acid_block.resource_url_passed) self.assertTrue(acid_block.scope_passed('content')) diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index 2dd8385498..5295759a96 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -23,4 +23,4 @@ -e git+https://github.com/edx/event-tracking.git@f0211d702d#egg=event-tracking -e git+https://github.com/edx/bok-choy.git@62de7b576a08f36cde5b030c52bccb1a2f3f8df1#egg=bok_choy -e git+https://github.com/edx-solutions/django-splash.git@15bf143b15714e22fc451ff1b0f8a7a2a9483172#egg=django-splash --e git+https://github.com/edx/acid-block.git@ce4c09615055a3cc14e39689e881c3422ff3162c#egg=acid-xblock +-e git+https://github.com/edx/acid-block.git@bf61f0fcd5916a9236bb5681c98374a48a13a74c#egg=acid-xblock