diff --git a/cms/djangoapps/contentstore/views/preview.py b/cms/djangoapps/contentstore/views/preview.py index 28b81316ad..33951a6089 100644 --- a/cms/djangoapps/contentstore/views/preview.py +++ b/cms/djangoapps/contentstore/views/preview.py @@ -131,6 +131,7 @@ def _preview_module_system(request, descriptor): # get_user_role accepts a location or a CourseLocator. # If descriptor.location is a CourseLocator, course_id is unused. get_user_role=lambda: get_user_role(request.user, descriptor.location, course_id), + descriptor_runtime=descriptor.runtime, ) @@ -158,6 +159,6 @@ def get_preview_fragment(request, descriptor): try: fragment = module.render("student_view") except Exception as exc: # pylint: disable=W0703 - log.debug("Unable to render student_view for %r", module, exc_info=True) + log.warning("Unable to render student_view for %r", module, exc_info=True) fragment = Fragment(render_to_string('html_error.html', {'message': str(exc)})) return fragment diff --git a/cms/static/coffee/src/xblock/cms.runtime.v1.coffee b/cms/static/coffee/src/xblock/cms.runtime.v1.coffee index 4eddd6ef3a..b420a6f33c 100644 --- a/cms/static/coffee/src/xblock/cms.runtime.v1.coffee +++ b/cms/static/coffee/src/xblock/cms.runtime.v1.coffee @@ -3,7 +3,7 @@ define ["jquery", "xblock/runtime.v1", "URI"], ($, XBlock, URI) -> class PreviewRuntime.v1 extends XBlock.Runtime.v1 handlerUrl: (element, handlerName, suffix, query, thirdparty) -> - uri = URI("/preview/xblock").segment($(@element).data('usage-id')) + uri = URI("/preview/xblock").segment($(element).data('usage-id')) .segment('handler') .segment(handlerName) if suffix? then uri.segment(suffix) @@ -14,7 +14,7 @@ define ["jquery", "xblock/runtime.v1", "URI"], ($, XBlock, URI) -> class StudioRuntime.v1 extends XBlock.Runtime.v1 handlerUrl: (element, handlerName, suffix, query, thirdparty) -> - uri = URI("/xblock").segment($(@element).data('usage-id')) + uri = URI("/xblock").segment($(element).data('usage-id')) .segment('handler') .segment(handlerName) if suffix? then uri.segment(suffix) diff --git a/common/lib/xmodule/xmodule/tests/__init__.py b/common/lib/xmodule/xmodule/tests/__init__.py index 28e612926a..4dce45af91 100644 --- a/common/lib/xmodule/xmodule/tests/__init__.py +++ b/common/lib/xmodule/xmodule/tests/__init__.py @@ -78,6 +78,7 @@ def get_test_system(course_id=''): course_id=course_id, error_descriptor_class=ErrorDescriptor, get_user_role=Mock(is_staff=False), + descriptor_runtime=get_test_descriptor_system(), ) diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index 484f0c9032..a136edcdaf 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -1048,7 +1048,7 @@ class ModuleSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable=abs """ def __init__( self, static_url, track_function, get_module, render_template, - replace_urls, user=None, filestore=None, + replace_urls, descriptor_runtime, user=None, filestore=None, debug=False, hostname="", xqueue=None, publish=None, node_path="", anonymous_student_id='', course_id=None, open_ended_grading_interface=None, s3_interface=None, @@ -1089,6 +1089,8 @@ class ModuleSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable=abs that capa_module can use to fix up the static urls in ajax results. + descriptor_runtime - A `DescriptorSystem` to use for loading xblocks by id + anonymous_student_id - Used for tracking modules with student id course_id - the course_id containing this module @@ -1148,6 +1150,7 @@ class ModuleSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable=abs self.get_real_user = get_real_user self.get_user_role = get_user_role + self.descriptor_runtime = descriptor_runtime def get(self, attr): """ provide uniform access to attributes (like etree).""" @@ -1172,7 +1175,7 @@ class ModuleSystem(ConfigurableFragmentWrapper, Runtime): # pylint: disable=abs return self.handler_url(self.xmodule_instance, 'xmodule_handler', '', '').rstrip('/?') def get_block(self, block_id): - raise NotImplementedError("XModules must use get_module to load other modules") + return self.get_module(self.descriptor_runtime.get_block(block_id)) def resource_url(self, resource): raise NotImplementedError("edX Platform doesn't currently implement XBlock resource urls") diff --git a/common/static/coffee/spec/xblock/core_spec.coffee b/common/static/coffee/spec/xblock/core_spec.coffee index efc6d15807..c71905b5a2 100644 --- a/common/static/coffee/spec/xblock/core_spec.coffee +++ b/common/static/coffee/spec/xblock/core_spec.coffee @@ -31,8 +31,8 @@ describe "XBlock", -> @missingInitBlock = XBlock.initializeBlock($('#missing-init')[0]) it "loads the right runtime version", -> - expect(TestRuntime.vA).toHaveBeenCalledWith($('#vA')[0], @fakeChildren) - expect(TestRuntime.vZ).toHaveBeenCalledWith($('#vZ')[0], @fakeChildren) + expect(TestRuntime.vA).toHaveBeenCalledWith() + expect(TestRuntime.vZ).toHaveBeenCalledWith() it "loads the right init function", -> expect(window.initFnA).toHaveBeenCalledWith(@runtimeA, $('#vA')[0]) diff --git a/common/static/coffee/spec/xblock/runtime.v1_spec.coffee b/common/static/coffee/spec/xblock/runtime.v1_spec.coffee index f13d69154c..7bad77494d 100644 --- a/common/static/coffee/spec/xblock/runtime.v1_spec.coffee +++ b/common/static/coffee/spec/xblock/runtime.v1_spec.coffee @@ -9,12 +9,13 @@ describe "XBlock.Runtime.v1", -> ] @element = $('.xblock')[0] + $(@element).prop('xblock_children', @children) - @runtime = new XBlock.Runtime.v1(@element, @children) + @runtime = new XBlock.Runtime.v1(@element) it "provides a list of children", -> - expect(@runtime.children).toBe(@children) + expect(@runtime.children(@element)).toBe(@children) it "maps children by name", -> - expect(@runtime.childMap.childA).toBe(@children[0]) - expect(@runtime.childMap.childB).toBe(@children[1]) + expect(@runtime.childMap(@element, 'childA')).toBe(@children[0]) + expect(@runtime.childMap(@element, 'childB')).toBe(@children[1]) diff --git a/common/static/coffee/src/xblock/core.coffee b/common/static/coffee/src/xblock/core.coffee index 9c5cc0961c..72768cac63 100644 --- a/common/static/coffee/src/xblock/core.coffee +++ b/common/static/coffee/src/xblock/core.coffee @@ -7,8 +7,9 @@ runtime = $element.data("runtime-class") version = $element.data("runtime-version") initFnName = $element.data("init") + $element.prop('xblock_children', children) if runtime? and version? and initFnName? - runtime = new window[runtime]["v#{version}"](element, children) + runtime = new window[runtime]["v#{version}"] initFn = window[initFnName] block = initFn(runtime, element) ? {} else diff --git a/common/static/coffee/src/xblock/runtime.v1.coffee b/common/static/coffee/src/xblock/runtime.v1.coffee index b3f28242ab..e7955306be 100644 --- a/common/static/coffee/src/xblock/runtime.v1.coffee +++ b/common/static/coffee/src/xblock/runtime.v1.coffee @@ -1,5 +1,5 @@ class XBlock.Runtime.v1 - constructor: (@element, @children) -> - @childMap = {} - $.each @children, (idx, child) => - @childMap[child.name] = child + children: (block) => $(block).prop('xblock_children') + childMap: (block, childName) => + for child in @children(block) + return child if child.name == childName \ No newline at end of file diff --git a/common/test/acceptance/pages/studio/unit.py b/common/test/acceptance/pages/studio/unit.py index e082d23d8d..9be786bcde 100644 --- a/common/test/acceptance/pages/studio/unit.py +++ b/common/test/acceptance/pages/studio/unit.py @@ -4,7 +4,7 @@ Unit page in Studio from bok_choy.page_object import PageObject from bok_choy.query import SubQuery -from bok_choy.promise import Promise, EmptyPromise, fulfill +from bok_choy.promise import EmptyPromise, fulfill from . import BASE_URL @@ -24,20 +24,32 @@ class UnitPage(PageObject): return "{}/unit/{}".format(BASE_URL, self.unit_locator) def is_browser_on_page(self): - return self.is_css_present('body.view-unit') + # Wait until all components have been loaded + return ( + self.is_css_present('body.view-unit') and + len(self.q(css=Component.BODY_SELECTOR)) == len(self.q(css='{} .xblock-student_view'.format(Component.BODY_SELECTOR))) + ) - def component(self, title): - return Component(self.browser, self._locator(title)) + @property + def components(self): + """ + Return a list of components loaded on the unit page. + """ + return self.q(css=Component.BODY_SELECTOR).map(lambda el: Component(self.browser, el['data-locator'])).results - def _locator(self, title): - def _check_func(): - locators = self.q(css=Component.BODY_SELECTOR).filter( - SubQuery(css=Component.NAME_SELECTOR).filter(text=title) - ).map(lambda el: el['data-locator']).results - - return (len(locators) > 0, locators[0]) - - return fulfill(Promise(_check_func, "Found data locator for component")) + def edit_draft(self): + """ + Started editing a draft of this unit. + """ + fulfill(EmptyPromise( + lambda: self.q(css='.create-draft').present, + 'Wait for edit draft link to be present' + )) + self.q(css='.create-draft').click() + fulfill(EmptyPromise( + lambda: self.q(css='.editing-draft-alert').present, + 'Wait for draft mode to be activated' + )) class Component(PageObject): diff --git a/common/test/acceptance/pages/xblock/acid.py b/common/test/acceptance/pages/xblock/acid.py index add30c3b91..4aa54e458c 100644 --- a/common/test/acceptance/pages/xblock/acid.py +++ b/common/test/acceptance/pages/xblock/acid.py @@ -51,6 +51,16 @@ class AcidView(PageObject): """ return self.test_passed('.document-ready-run') + @property + def child_tests_passed(self): + """ + Whether the tests of children passed + """ + return all([ + self.test_passed('.child-counts-match'), + self.test_passed('.child-values-match') + ]) + 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 bbad1ba4c9..2f0946f4c2 100644 --- a/common/test/acceptance/tests/test_lms.py +++ b/common/test/acceptance/tests/test_lms.py @@ -3,7 +3,7 @@ E2E tests for the LMS. """ -from unittest import skip +from unittest import skip, expectedFailure from bok_choy.web_app_test import WebAppTest from bok_choy.promise import EmptyPromise, fulfill_before, fulfill, Promise @@ -292,8 +292,9 @@ class VideoTest(UniqueCourseTest): course_fix.add_children( XBlockFixtureDesc('chapter', 'Test Section').add_children( XBlockFixtureDesc('sequential', 'Test Subsection').add_children( - XBlockFixtureDesc('video', 'Video') - ))).install() + XBlockFixtureDesc('vertical', 'Test Unit').add_children( + XBlockFixtureDesc('video', 'Video') + )))).install() # Auto-auth register for the course @@ -338,18 +339,48 @@ class VideoTest(UniqueCourseTest): self.assertGreaterEqual(self.video.duration, self.video.elapsed_time) -class XBlockAcidTest(UniqueCourseTest): +class XBlockAcidBase(UniqueCourseTest): """ - Tests that verify that XBlock integration is working correctly + Base class for tests that verify that XBlock integration is working correctly """ + __test__ = False def setUp(self): """ Create a unique identifier for the course used in this test. """ # Ensure that the superclass sets up - super(XBlockAcidTest, self).setUp() + super(XBlockAcidBase, self).setUp() + self.setup_fixtures() + + AutoAuthPage(self.browser, course_id=self.course_id).visit() + + self.course_info_page = CourseInfoPage(self.browser, self.course_id) + self.tab_nav = TabNavPage(self.browser) + + def test_acid_block(self): + """ + Verify that all expected acid block tests pass in the lms. + """ + + self.course_info_page.visit() + self.tab_nav.go_to_tab('Courseware') + + 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.scope_passed('user_state')) + + +class XBlockAcidNoChildTest(XBlockAcidBase): + """ + Tests of an AcidBlock with no children + """ + __test__ = True + + def setup_fixtures(self): course_fix = CourseFixture( self.course_info['org'], self.course_info['number'], @@ -360,24 +391,43 @@ class XBlockAcidTest(UniqueCourseTest): course_fix.add_children( XBlockFixtureDesc('chapter', 'Test Section').add_children( XBlockFixtureDesc('sequential', 'Test Subsection').add_children( - XBlockFixtureDesc('acid', 'Acid Block') + XBlockFixtureDesc('vertical', 'Test Unit').add_children( + XBlockFixtureDesc('acid', 'Acid Block') + ) ) ) ).install() - AutoAuthPage(self.browser, course_id=self.course_id).visit() - self.course_info_page = CourseInfoPage(self.browser, self.course_id) - self.tab_nav = TabNavPage(self.browser) +class XBlockAcidChildTest(XBlockAcidBase): + """ + Tests of an AcidBlock with children + """ + __test__ = True - self.course_info_page.visit() - self.tab_nav.go_to_tab('Courseware') + def setup_fixtures(self): + course_fix = CourseFixture( + self.course_info['org'], + self.course_info['number'], + self.course_info['run'], + self.course_info['display_name'] + ) + course_fix.add_children( + XBlockFixtureDesc('chapter', 'Test Section').add_children( + XBlockFixtureDesc('sequential', 'Test Subsection').add_children( + XBlockFixtureDesc('vertical', 'Test Unit').add_children( + XBlockFixtureDesc('acid', 'Acid Block').add_children( + XBlockFixtureDesc('acid', 'First Acid Child', metadata={'name': 'first'}), + XBlockFixtureDesc('acid', 'Second Acid Child', metadata={'name': 'second'}), + XBlockFixtureDesc('html', 'Html Child', data="Contents"), + ) + ) + ) + ) + ).install() + + # This will fail until we fix support of children in pure XBlocks + @expectedFailure def test_acid_block(self): - """ - Verify that all expected acid block tests pass in the lms. - """ - 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.scope_passed('user_state')) + super(XBlockAcidChildTest, self).test_acid_block() diff --git a/common/test/acceptance/tests/test_studio.py b/common/test/acceptance/tests/test_studio.py index 989533145d..17bfc0a75c 100644 --- a/common/test/acceptance/tests/test_studio.py +++ b/common/test/acceptance/tests/test_studio.py @@ -1,6 +1,8 @@ """ Acceptance tests for Studio. """ +from unittest import expectedFailure + from bok_choy.web_app_test import WebAppTest from ..pages.studio.asset_index import AssetIndexPage @@ -110,17 +112,18 @@ class CoursePagesTest(UniqueCourseTest): page.visit() -class XBlockAcidTest(WebAppTest): +class XBlockAcidBase(WebAppTest): """ - Tests that verify that XBlock integration is working correctly + Base class for tests that verify that XBlock integration is working correctly """ + __test__ = False def setUp(self): """ Create a unique identifier for the course used in this test. """ # Ensure that the superclass sets up - super(XBlockAcidTest, self).setUp() + super(XBlockAcidBase, self).setUp() # Define a unique course identifier self.course_info = { @@ -140,6 +143,50 @@ class XBlockAcidTest(WebAppTest): self.course_id = '{org}.{number}.{run}'.format(**self.course_info) + self.setup_fixtures() + + self.auth_page.visit() + + def test_acid_block_preview(self): + """ + Verify that all expected acid block tests pass in studio preview + """ + + self.outline.visit() + unit = self.outline.section('Test Section').subsection('Test Subsection').toggle_expand().unit('Test Unit').go_to() + + 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.scope_passed('user_state')) + + def test_acid_block_editor(self): + """ + Verify that all expected acid block tests pass in studio preview + """ + + self.outline.visit() + unit = self.outline.section('Test Section').subsection('Test Subsection').toggle_expand().unit('Test Unit').go_to() + + unit.edit_draft() + + 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.scope_passed('content')) + self.assertTrue(acid_block.scope_passed('settings')) + + +class XBlockAcidNoChildTest(XBlockAcidBase): + """ + Tests of an AcidBlock with no children + """ + __test__ = True + + def setup_fixtures(self): + course_fix = CourseFixture( self.course_info['org'], self.course_info['number'], @@ -157,27 +204,42 @@ class XBlockAcidTest(WebAppTest): ) ).install() - self.auth_page.visit() - self.outline.visit() - unit = self.outline.section('Test Section').subsection('Test Subsection').toggle_expand().unit('Test Unit').go_to() - self.acid_component = unit.component('Acid Block') +class XBlockAcidChildTest(XBlockAcidBase): + """ + Tests of an AcidBlock with children + """ + __test__ = True + def setup_fixtures(self): + + course_fix = CourseFixture( + self.course_info['org'], + self.course_info['number'], + self.course_info['run'], + self.course_info['display_name'] + ) + + course_fix.add_children( + XBlockFixtureDesc('chapter', 'Test Section').add_children( + XBlockFixtureDesc('sequential', 'Test Subsection').add_children( + XBlockFixtureDesc('vertical', 'Test Unit').add_children( + XBlockFixtureDesc('acid', 'Acid Block').add_children( + XBlockFixtureDesc('acid', 'First Acid Child', metadata={'name': 'first'}), + XBlockFixtureDesc('acid', 'Second Acid Child', metadata={'name': 'second'}), + XBlockFixtureDesc('html', 'Html Child', data="Contents"), + ) + ) + ) + ) + ).install() + + # This will fail until we fix support of children in pure XBlocks + @expectedFailure def test_acid_block_preview(self): - """ - Verify that all expected acid block tests pass in studio preview - """ - acid_block = AcidView(self.browser, self.acid_component.preview_selector) - self.assertTrue(acid_block.init_fn_passed) - self.assertTrue(acid_block.doc_ready_passed) - self.assertTrue(acid_block.scope_passed('user_state')) + super(XBlockAcidChildTest, self).test_acid_block_preview() + # This will fail until we fix support of children in pure XBlocks + @expectedFailure def test_acid_block_editor(self): - """ - Verify that all expected acid block tests pass in studio preview - """ - acid_block = AcidView(self.browser, self.acid_component.edit().editor_selector) - self.assertTrue(acid_block.init_fn_passed) - self.assertTrue(acid_block.doc_ready_passed) - self.assertTrue(acid_block.scope_passed('content')) - self.assertTrue(acid_block.scope_passed('settings')) + super(XBlockAcidChildTest, self).test_acid_block_editor() diff --git a/lms/djangoapps/courseware/module_render.py b/lms/djangoapps/courseware/module_render.py index 382131f262..f636ccea7c 100644 --- a/lms/djangoapps/courseware/module_render.py +++ b/lms/djangoapps/courseware/module_render.py @@ -227,7 +227,6 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours return None student_data = KvsFieldData(DjangoKeyValueStore(field_data_cache)) - descriptor._field_data = LmsFieldData(descriptor._field_data, student_data) def make_xqueue_callback(dispatch='score_update'): @@ -433,6 +432,7 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours 'i18n': ModuleI18nService(), }, get_user_role=lambda: get_user_role(user, course_id), + descriptor_runtime=descriptor.runtime, ) # pass position specified in URL to module through ModuleSystem @@ -451,8 +451,8 @@ def get_module_for_descriptor_internal(user, descriptor, field_data_cache, cours else: system.error_descriptor_class = NonStaffErrorDescriptor - descriptor.xmodule_runtime = system - descriptor.scope_ids = descriptor.scope_ids._replace(user_id=user.id) + descriptor.bind_for_student(system, LmsFieldData(descriptor._field_data, student_data)) # pylint: disable=protected-access + descriptor.scope_ids = descriptor.scope_ids._replace(user_id=user.id) # pylint: disable=protected-access return descriptor diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 0dd527ed2b..8c7357087b 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -2,6 +2,7 @@ Test for lms courseware app, module render unit """ from ddt import ddt, data +from functools import partial from mock import MagicMock, patch, Mock import json @@ -657,6 +658,9 @@ class TestAnonymousStudentId(ModuleStoreTestCase, LoginEnrollmentTestCase): ), 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 diff --git a/lms/djangoapps/open_ended_grading/open_ended_notifications.py b/lms/djangoapps/open_ended_grading/open_ended_notifications.py index 9398a11957..4962f8efa9 100644 --- a/lms/djangoapps/open_ended_grading/open_ended_notifications.py +++ b/lms/djangoapps/open_ended_grading/open_ended_notifications.py @@ -69,6 +69,7 @@ def peer_grading_notifications(course, user): get_module=None, render_template=render_to_string, replace_urls=None, + descriptor_runtime=None, ) peer_gs = peer_grading_service.PeerGradingService(settings.OPEN_ENDED_GRADING_INTERFACE, system) pending_grading = False @@ -129,6 +130,7 @@ def combined_notifications(course, user): get_module=None, render_template=render_to_string, replace_urls=None, + descriptor_runtime=None, ) #Initialize controller query service using our mock system controller_qs = ControllerQueryService(settings.OPEN_ENDED_GRADING_INTERFACE, system) diff --git a/lms/djangoapps/open_ended_grading/staff_grading_service.py b/lms/djangoapps/open_ended_grading/staff_grading_service.py index 81a2eb401c..dad93fbc28 100644 --- a/lms/djangoapps/open_ended_grading/staff_grading_service.py +++ b/lms/djangoapps/open_ended_grading/staff_grading_service.py @@ -83,6 +83,7 @@ class StaffGradingService(GradingService): get_module=None, render_template=render_to_string, replace_urls=None, + descriptor_runtime=None, ) super(StaffGradingService, self).__init__(config) self.url = config['url'] + config['staff_grading'] diff --git a/lms/djangoapps/open_ended_grading/tests.py b/lms/djangoapps/open_ended_grading/tests.py index 517d3d8824..8ac9bab50f 100644 --- a/lms/djangoapps/open_ended_grading/tests.py +++ b/lms/djangoapps/open_ended_grading/tests.py @@ -285,6 +285,7 @@ class TestPeerGradingService(ModuleStoreTestCase, LoginEnrollmentTestCase): open_ended_grading_interface=test_util_open_ended.OPEN_ENDED_GRADING_INTERFACE, mixins=settings.XBLOCK_MIXINS, error_descriptor_class=ErrorDescriptor, + descriptor_runtime=None, ) self.descriptor = peer_grading_module.PeerGradingDescriptor(self.system, field_data, ScopeIds(None, None, None, None)) self.descriptor.xmodule_runtime = self.system diff --git a/lms/djangoapps/open_ended_grading/utils.py b/lms/djangoapps/open_ended_grading/utils.py index 01d58fb479..9f60289a2d 100644 --- a/lms/djangoapps/open_ended_grading/utils.py +++ b/lms/djangoapps/open_ended_grading/utils.py @@ -33,6 +33,7 @@ SYSTEM = LmsModuleSystem( get_module=None, render_template=render_to_string, replace_urls=None, + descriptor_runtime=None, ) diff --git a/lms/lib/xblock/test/test_runtime.py b/lms/lib/xblock/test/test_runtime.py index 14987a87d3..63fd2fe763 100644 --- a/lms/lib/xblock/test/test_runtime.py +++ b/lms/lib/xblock/test/test_runtime.py @@ -48,6 +48,7 @@ class TestHandlerUrl(TestCase): render_template=Mock(), replace_urls=str, course_id=self.course_id, + descriptor_runtime=Mock(), ) def test_trailing_characters(self): diff --git a/lms/static/coffee/src/xblock/lms.runtime.v1.coffee b/lms/static/coffee/src/xblock/lms.runtime.v1.coffee index 9a999727a3..f10b1ae1c5 100644 --- a/lms/static/coffee/src/xblock/lms.runtime.v1.coffee +++ b/lms/static/coffee/src/xblock/lms.runtime.v1.coffee @@ -2,8 +2,8 @@ class LmsRuntime.v1 extends XBlock.Runtime.v1 handlerUrl: (element, handlerName, suffix, query, thirdparty) -> - courseId = $(@element).data("course-id") - usageId = $(@element).data("usage-id") + courseId = $(element).data("course-id") + usageId = $(element).data("usage-id") handlerAuth = if thirdparty then "handler_noauth" else "handler" uri = URI('/courses').segment(courseId) diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index f08722afed..c8cb2c4897 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -21,6 +21,6 @@ -e git+https://github.com/edx/js-test-tool.git@v0.1.5#egg=js_test_tool -e git+https://github.com/edx/django-waffle.git@823a102e48#egg=django-waffle -e git+https://github.com/edx/event-tracking.git@f0211d702d#egg=event-tracking --e git+https://github.com/edx/bok-choy.git@v0.2.1#egg=bok_choy +-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@aa95a3c#egg=acid-xblock +-e git+https://github.com/edx/acid-block.git@9c832513f0c01f79227bea894fba11c66fe4c08c#egg=acid-xblock