test: Allow for Extracted Word Cloud Block | Fix Test Cases (#35983)
Run tests for both the built-in and extracted WordCloud block. The tests are mostly compatible with both versions of the block, except for a few places where the XBlock framework and the built-in XModule system differ which we've had to handle using conditionals. This moves us closer to enabling the extracted WordCloud block by default and eventually removing the built-in block. Part of: https://github.com/openedx/edx-platform/issues/34840
This commit is contained in:
committed by
GitHub
parent
17f0e256bd
commit
4a9fc77ecb
@@ -138,11 +138,11 @@ class BaseTestXmodule(ModuleStoreTestCase):
|
||||
self.setup_course()
|
||||
self.initialize_module(metadata=self.METADATA, data=self.DATA)
|
||||
|
||||
def get_url(self, dispatch):
|
||||
def get_url(self, dispatch, handler_name='xmodule_handler'):
|
||||
"""Return item url with dispatch."""
|
||||
return reverse(
|
||||
'xblock_handler',
|
||||
args=(str(self.course.id), quote_slashes(self.item_url), 'xmodule_handler', dispatch)
|
||||
args=(str(self.course.id), quote_slashes(self.item_url), handler_name, dispatch)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,23 +1,40 @@
|
||||
"""Word cloud integration tests using mongo modulestore."""
|
||||
|
||||
import importlib
|
||||
import json
|
||||
import re
|
||||
from operator import itemgetter
|
||||
from unittest.mock import patch
|
||||
from uuid import UUID
|
||||
|
||||
import pytest
|
||||
from django.conf import settings
|
||||
from django.test import override_settings
|
||||
from xblock import plugin
|
||||
|
||||
import json
|
||||
from operator import itemgetter
|
||||
|
||||
from common.djangoapps.student.tests.factories import RequestFactoryNoCsrf
|
||||
from xmodule import word_cloud_block
|
||||
# noinspection PyUnresolvedReferences
|
||||
from xmodule.tests.helpers import override_descriptor_system # pylint: disable=unused-import
|
||||
from xmodule.tests.helpers import override_descriptor_system, mock_render_template # pylint: disable=unused-import
|
||||
from xmodule.x_module import STUDENT_VIEW
|
||||
|
||||
from .helpers import BaseTestXmodule
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("override_descriptor_system")
|
||||
class TestWordCloud(BaseTestXmodule):
|
||||
class _TestWordCloudBase(BaseTestXmodule):
|
||||
"""Integration test for Word Cloud Block."""
|
||||
__test__ = False
|
||||
CATEGORY = "word_cloud"
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
plugin.PLUGIN_CACHE = {}
|
||||
importlib.reload(word_cloud_block)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.request_factory = RequestFactoryNoCsrf()
|
||||
|
||||
def _get_users_state(self):
|
||||
"""Return current state for each user:
|
||||
|
||||
@@ -27,7 +44,18 @@ class TestWordCloud(BaseTestXmodule):
|
||||
users_state = {}
|
||||
|
||||
for user in self.users:
|
||||
response = self.clients[user.username].post(self.get_url('get_state'))
|
||||
if settings.USE_EXTRACTED_WORD_CLOUD_BLOCK:
|
||||
# The extracted Word Cloud XBlock uses @XBlock.json_handler, which expects a different
|
||||
# request format and url pattern
|
||||
handler_url = self.get_url('', handler_name='handle_get_state')
|
||||
response = self.clients[user.username].post(
|
||||
handler_url,
|
||||
data=json.dumps({}),
|
||||
content_type='application/json',
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest',
|
||||
)
|
||||
else:
|
||||
response = self.clients[user.username].post(self.get_url('get_state'))
|
||||
users_state[user.username] = json.loads(response.content.decode('utf-8'))
|
||||
|
||||
return users_state
|
||||
@@ -40,11 +68,22 @@ class TestWordCloud(BaseTestXmodule):
|
||||
users_state = {}
|
||||
|
||||
for user in self.users:
|
||||
response = self.clients[user.username].post(
|
||||
self.get_url('submit'),
|
||||
{'student_words[]': words},
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
|
||||
)
|
||||
if settings.USE_EXTRACTED_WORD_CLOUD_BLOCK:
|
||||
# The extracted Word Cloud XBlock uses @XBlock.json_handler, which expects a different
|
||||
# request format and url pattern
|
||||
handler_url = self.get_url('', handler_name='handle_submit_state')
|
||||
response = self.clients[user.username].post(
|
||||
handler_url,
|
||||
data=json.dumps({'student_words': words}),
|
||||
content_type='application/json',
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest',
|
||||
)
|
||||
else:
|
||||
response = self.clients[user.username].post(
|
||||
self.get_url('submit'),
|
||||
{'student_words[]': words},
|
||||
HTTP_X_REQUESTED_WITH='XMLHttpRequest'
|
||||
)
|
||||
users_state[user.username] = json.loads(response.content.decode('utf-8'))
|
||||
|
||||
return users_state
|
||||
@@ -52,7 +91,6 @@ class TestWordCloud(BaseTestXmodule):
|
||||
def _check_response(self, response_contents, correct_jsons):
|
||||
"""Utility function that compares correct and real responses."""
|
||||
for username, content in response_contents.items():
|
||||
|
||||
# Used in debugger for comparing objects.
|
||||
# self.maxDiff = None
|
||||
|
||||
@@ -120,7 +158,6 @@ class TestWordCloud(BaseTestXmodule):
|
||||
|
||||
correct_state = {}
|
||||
for index, user in enumerate(self.users):
|
||||
|
||||
correct_state[user.username] = {
|
||||
'status': 'success',
|
||||
'submitted': True,
|
||||
@@ -202,6 +239,14 @@ class TestWordCloud(BaseTestXmodule):
|
||||
for user in self.users
|
||||
}
|
||||
|
||||
if settings.USE_EXTRACTED_WORD_CLOUD_BLOCK:
|
||||
# The extracted Word Cloud XBlock uses @XBlock.json_handler to handle AJAX requests,
|
||||
# which automatically returns a 404 for unknown requests, so there's no need to test
|
||||
# the incorrect dispatch case in this scenario.
|
||||
for username, response in responses.items():
|
||||
self.assertEqual(response.status_code, 404)
|
||||
return
|
||||
|
||||
status_codes = {response.status_code for response in responses.values()}
|
||||
assert status_codes.pop() == 200
|
||||
|
||||
@@ -214,19 +259,44 @@ class TestWordCloud(BaseTestXmodule):
|
||||
}
|
||||
)
|
||||
|
||||
def test_word_cloud_constructor(self):
|
||||
@patch('xblock.utils.resources.ResourceLoader.render_django_template', side_effect=mock_render_template)
|
||||
def test_word_cloud_constructor(self, mock_render_django_template):
|
||||
"""
|
||||
Make sure that all parameters extracted correctly from xml.
|
||||
"""
|
||||
fragment = self.runtime.render(self.block, STUDENT_VIEW)
|
||||
expected_context = {
|
||||
'ajax_url': self.block.ajax_url,
|
||||
'display_name': self.block.display_name,
|
||||
'instructions': self.block.instructions,
|
||||
'element_class': self.block.location.block_type,
|
||||
'element_id': self.block.location.html_id(),
|
||||
'element_class': self.block.scope_ids.block_type,
|
||||
'num_inputs': 5, # default value
|
||||
'submitted': False, # default value,
|
||||
}
|
||||
|
||||
assert fragment.content == self.runtime.render_template('word_cloud.html', expected_context)
|
||||
if settings.USE_EXTRACTED_WORD_CLOUD_BLOCK:
|
||||
# If `USE_EXTRACTED_WORD_CLOUD_BLOCK` is enabled, the `expected_context` will be different
|
||||
# because in the extracted Word Cloud XBlock, the expected context:
|
||||
# - contains `range_num_inputs`
|
||||
# - uses `UUID` for `element_id` instead of `html_id()`
|
||||
# - does not include `ajax_url` since it uses the `@XBlock.json_handler` decorator for AJAX requests
|
||||
expected_context['range_num_inputs'] = range(5)
|
||||
uuid_str = re.search(r"UUID\('([a-f0-9\-]+)'\)", fragment.content).group(1)
|
||||
expected_context['element_id'] = UUID(uuid_str)
|
||||
mock_render_django_template.assert_called_once()
|
||||
# Remove i18n service
|
||||
fragment_content_clean = re.sub(r"\{.*?}", "{}", fragment.content)
|
||||
assert fragment_content_clean == self.runtime.render_template('templates/word_cloud.html', expected_context)
|
||||
else:
|
||||
expected_context['ajax_url'] = self.block.ajax_url
|
||||
expected_context['element_id'] = self.block.location.html_id()
|
||||
assert fragment.content == self.runtime.render_template('word_cloud.html', expected_context)
|
||||
|
||||
|
||||
@override_settings(USE_EXTRACTED_WORD_CLOUD_BLOCK=True)
|
||||
class TestWordCloudExtracted(_TestWordCloudBase):
|
||||
__test__ = True
|
||||
|
||||
|
||||
@override_settings(USE_EXTRACTED_WORD_CLOUD_BLOCK=False)
|
||||
class TestWordCloudBuiltIn(_TestWordCloudBase):
|
||||
__test__ = True
|
||||
|
||||
Reference in New Issue
Block a user