refactor: deprecates ModuleSystem.render_template

in favor of the added MakoSystem render_template method.

Related changes:
* Adds the MakoService to the StudioEditModuleRuntime,
  PreviewModuleSystem, LmsModuleSystem, and XBlockRuntime
* MakoService constructor takes a `namespace_prefix` string, so that the
  CMS PreviewModuleSystem can render to LMS templates, without needing
  the special render_from_lms helper method.
* ModuleSystem.render_template becomes a read-only property, so the
  constructor calls and test module systems are updated accordingly.
* Adds tests for the MakoService and module system shims.
This commit is contained in:
Jillian Vogel
2021-10-05 12:38:42 +10:30
parent 480e8997ec
commit 457f959356
21 changed files with 219 additions and 84 deletions

View File

@@ -52,7 +52,6 @@ from lms.djangoapps.courseware.masquerade import (
setup_masquerade
)
from lms.djangoapps.courseware.model_data import DjangoKeyValueStore, FieldDataCache
from common.djangoapps.edxmako.shortcuts import render_to_string
from lms.djangoapps.courseware.field_overrides import OverrideFieldData
from lms.djangoapps.courseware.services import UserStateService
from lms.djangoapps.grades.api import GradesUtilService
@@ -90,6 +89,7 @@ from common.djangoapps.student.roles import CourseBetaTesterRole
from common.djangoapps.track import contexts
from common.djangoapps.util import milestones_helpers
from common.djangoapps.util.json_request import JsonResponse
from common.djangoapps.edxmako.services import MakoService
from common.djangoapps.xblock_django.user_service import DjangoXBlockUserService
from xmodule.contentstore.django import contentstore
from xmodule.error_module import ErrorBlock, NonStaffErrorBlock
@@ -703,6 +703,7 @@ def get_module_system_for_user(
if is_masquerading_as_specific_student(user, course_id):
block_wrappers.append(filter_displayed_blocks)
mako_service = MakoService()
if settings.FEATURES.get("LICENSING", False):
block_wrappers.append(wrap_with_license)
@@ -770,7 +771,6 @@ def get_module_system_for_user(
system = LmsModuleSystem(
track_function=track_function,
render_template=render_to_string,
static_url=settings.STATIC_URL,
xqueue=xqueue,
# TODO (cpennington): Figure out how to share info between systems
@@ -810,6 +810,7 @@ def get_module_system_for_user(
services={
'fs': FSService(),
'field-data': field_data,
'mako': mako_service,
'user': user_service,
'verification': XBlockVerificationService(),
'proctoring': ProctoringService(),

View File

@@ -7,6 +7,7 @@ import ast
import json
from collections import OrderedDict
from datetime import timedelta
from unittest.mock import Mock
from django.contrib import messages
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
@@ -63,11 +64,11 @@ class BaseTestXmodule(ModuleStoreTestCase):
METADATA = {}
MODEL_DATA = {'data': '<some_module></some_module>'}
def new_module_runtime(self):
def new_module_runtime(self, render_template=None):
"""
Generate a new ModuleSystem that is minimally set up for testing
"""
return get_test_system(course_id=self.course.id)
return get_test_system(course_id=self.course.id, render_template=render_template)
def new_descriptor_runtime(self):
runtime = get_test_descriptor_system()
@@ -143,12 +144,14 @@ class BaseTestXmodule(ModuleStoreTestCase):
class XModuleRenderingTestBase(BaseTestXmodule): # lint-amnesty, pylint: disable=missing-class-docstring
def new_module_runtime(self):
def new_module_runtime(self, render_template=None):
"""
Create a runtime that actually does html rendering
"""
runtime = super().new_module_runtime()
runtime.render_template = render_to_string
if not render_template:
render_template = render_to_string
runtime = super().new_module_runtime(render_template=render_template)
runtime.modulestore = Mock()
return runtime

View File

@@ -42,7 +42,6 @@ class TestDiscussionXBlock(XModuleRenderingTestBase):
self.patchers = []
self.course_id = "test_course"
self.runtime = self.new_module_runtime()
self.runtime.modulestore = mock.Mock()
self.discussion_id = str(uuid.uuid4())
self.data = DictFieldData({
@@ -131,7 +130,8 @@ class TestViews(TestDiscussionXBlock):
self.template_canary = 'canary'
self.render_template = mock.Mock()
self.render_template.return_value = self.template_canary
self.block.runtime.render_template = self.render_template
self.runtime = self.new_module_runtime(render_template=self.render_template)
self.block.runtime = self.runtime
self.has_permission_mock = mock.Mock()
self.has_permission_mock.return_value = False
self.block.has_permission = self.has_permission_mock

View File

@@ -2687,3 +2687,17 @@ class LmsModuleSystemShimTest(SharedModuleStoreTestCase):
assert runtime.seed == 0
assert runtime.user_id is None
assert not runtime.user_is_staff
def test_render_template(self):
runtime, _ = render.get_module_system_for_user(
self.user,
self.student_data,
self.descriptor,
self.course.id,
self.track_function,
self.xqueue_callback_url_prefix,
self.request_token,
course=self.course,
)
rendered = runtime.render_template('templates/edxmako.html', {'element_id': 'hi'}) # pylint: disable=not-callable
assert rendered == '<div id="hi" ns="main">Testing the MakoService</div>\n'

View File

@@ -63,7 +63,6 @@ class TestHandlerUrl(TestCase):
static_url='/static',
track_function=Mock(),
get_module=Mock(),
render_template=Mock(),
replace_urls=str,
course_id=self.course_key,
user=Mock(),
@@ -130,7 +129,6 @@ class TestUserServiceAPI(TestCase):
static_url='/static',
track_function=Mock(),
get_module=Mock(),
render_template=Mock(),
replace_urls=str,
user=self.user,
course_id=self.course_id,
@@ -186,7 +184,6 @@ class TestBadgingService(ModuleStoreTestCase):
static_url='/static',
track_function=Mock(),
get_module=Mock(),
render_template=Mock(),
replace_urls=str,
course_id=self.course_id,
user=self.user,
@@ -242,7 +239,6 @@ class TestI18nService(ModuleStoreTestCase):
static_url='/static',
track_function=Mock(),
get_module=Mock(),
render_template=Mock(),
replace_urls=str,
course_id=self.course.id,
user=Mock(),

View File

@@ -495,6 +495,20 @@ ENTERPRISE_CONSENT_API_URL = 'http://enterprise.example.com/consent/api/v1/'
ACTIVATION_EMAIL_FROM_ADDRESS = 'test_activate@edx.org'
TEMPLATES[0]['OPTIONS']['debug'] = True
TEMPLATES.append(
{
# This separate copy of the Mako backend is used to test rendering previews in the 'lms.main' namespace
'NAME': 'preview',
'BACKEND': 'common.djangoapps.edxmako.backend.Mako',
'APP_DIRS': False,
'DIRS': MAKO_TEMPLATE_DIRS_BASE,
'OPTIONS': {
'context_processors': CONTEXT_PROCESSORS,
'debug': False,
'namespace': 'lms.main',
}
}
)
########################## VIDEO TRANSCRIPTS STORAGE ############################
VIDEO_TRANSCRIPTS_SETTINGS = dict(