Merge branch 'master' into issue-35271-unpin-markdown

This commit is contained in:
Ram Chandra Bhavirisetty
2025-05-19 21:33:19 -06:00
committed by GitHub
26 changed files with 271 additions and 127 deletions

View File

@@ -64,7 +64,7 @@ def test_compile_xblock_translations(tmp_translations_dir):
'msgfmt', '--check-format', '-o', str(po_file.with_suffix('.mo')), str(po_file), 'msgfmt', '--check-format', '-o', str(po_file.with_suffix('.mo')), str(po_file),
], 'Compiles the .po files' ], 'Compiles the .po files'
js_file_text = get_javascript_i18n_file_path('done', 'tr').text() js_file_text = get_javascript_i18n_file_path('done', 'tr').read_text()
assert 'Merhaba' in js_file_text, 'Ensures the JavaScript catalog is compiled' assert 'Merhaba' in js_file_text, 'Ensures the JavaScript catalog is compiled'
assert 'TestingDoneXBlockI18n' in js_file_text, 'Ensures the namespace is used' assert 'TestingDoneXBlockI18n' in js_file_text, 'Ensures the namespace is used'
assert 'gettext' in js_file_text, 'Ensures the gettext function is defined' assert 'gettext' in js_file_text, 'Ensures the gettext function is defined'

View File

@@ -101,7 +101,7 @@ def compile_xblock_js_messages():
xblock_conf_locale_dir = xmodule_api.get_python_locale_root() / xblock_module xblock_conf_locale_dir = xmodule_api.get_python_locale_root() / xblock_module
i18n_js_namespace = xblock_class.get_i18n_js_namespace() i18n_js_namespace = xblock_class.get_i18n_js_namespace()
for locale_dir in xblock_conf_locale_dir.listdir(): for locale_dir in xblock_conf_locale_dir.iterdir():
locale_code = str(locale_dir.basename()) locale_code = str(locale_dir.basename())
locale_messages_dir = locale_dir / 'LC_MESSAGES' locale_messages_dir = locale_dir / 'LC_MESSAGES'
js_translations_domain = None js_translations_domain = None

View File

@@ -11,7 +11,7 @@ which communicate with edx-platform over AJAX, but are built and deployed
independently. Eventually, we expect that MFEs will replace all edx-platform independently. Eventually, we expect that MFEs will replace all edx-platform
frontend pages, except perhaps XBlock views.* frontend pages, except perhaps XBlock views.*
Configuraiton Configuration
************* *************
To customize the static assets build, set some or all of these variable in your To customize the static assets build, set some or all of these variable in your

View File

@@ -52,6 +52,7 @@ from .documents import (
searchable_doc_for_key, searchable_doc_for_key,
searchable_doc_tags, searchable_doc_tags,
searchable_doc_tags_for_collection, searchable_doc_tags_for_collection,
searchable_doc_units,
) )
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -451,6 +452,7 @@ def rebuild_index(status_cb: Callable[[str], None] | None = None, incremental=Fa
doc.update(searchable_doc_for_library_block(metadata)) doc.update(searchable_doc_for_library_block(metadata))
doc.update(searchable_doc_tags(metadata.usage_key)) doc.update(searchable_doc_tags(metadata.usage_key))
doc.update(searchable_doc_collections(metadata.usage_key)) doc.update(searchable_doc_collections(metadata.usage_key))
doc.update(searchable_doc_units(metadata.usage_key))
docs.append(doc) docs.append(doc)
except Exception as err: # pylint: disable=broad-except except Exception as err: # pylint: disable=broad-except
status_cb(f"Error indexing library component {component}: {err}") status_cb(f"Error indexing library component {component}: {err}")
@@ -853,6 +855,15 @@ def upsert_item_collections_index_docs(opaque_key: OpaqueKey):
_update_index_docs([doc]) _update_index_docs([doc])
def upsert_item_units_index_docs(opaque_key: OpaqueKey):
"""
Updates the units data in documents for the given Course/Library block
"""
doc = {Fields.id: meili_id_from_opaque_key(opaque_key)}
doc.update(searchable_doc_units(opaque_key))
_update_index_docs([doc])
def upsert_collection_tags_index_docs(collection_key: LibraryCollectionLocator): def upsert_collection_tags_index_docs(collection_key: LibraryCollectionLocator):
""" """
Updates the tags data in documents for the given library collection Updates the tags data in documents for the given library collection

View File

@@ -67,6 +67,10 @@ class Fields:
collections = "collections" collections = "collections"
collections_display_name = "display_name" collections_display_name = "display_name"
collections_key = "key" collections_key = "key"
# Units (dictionary) that this object belongs to.
units = "units"
units_display_name = "display_name"
units_key = "key"
# The "content" field is a dictionary of arbitrary data, depending on the block_type. # The "content" field is a dictionary of arbitrary data, depending on the block_type.
# It comes from each XBlock's index_dictionary() method (if present) plus some processing. # It comes from each XBlock's index_dictionary() method (if present) plus some processing.
@@ -369,6 +373,54 @@ def _collections_for_content_object(object_id: OpaqueKey) -> dict:
return result return result
def _units_for_content_object(object_id: OpaqueKey) -> dict:
"""
Given an XBlock, course, library, etc., get the units for its index doc.
e.g. for something in Units "UNIT_A" and "UNIT_B", this would return:
{
"units": {
"display_name": ["Unit A", "Unit B"],
"key": ["UNIT_A", "UNIT_B"],
}
}
If the object is in no collections, returns:
{
"collections": {
"display_name": [],
"key": [],
},
}
"""
result = {
Fields.units: {
Fields.units_display_name: [],
Fields.units_key: [],
}
}
# Gather the units associated with this object
units = None
try:
if isinstance(object_id, UsageKey):
units = lib_api.get_containers_contains_component(object_id)
else:
log.warning(f"Unexpected key type for {object_id}")
except ObjectDoesNotExist:
log.warning(f"No library item found for {object_id}")
if not units:
return result
for unit in units:
result[Fields.units][Fields.units_display_name].append(unit.display_name)
result[Fields.units][Fields.units_key].append(str(unit.container_key))
return result
def _published_data_from_block(block_published) -> dict: def _published_data_from_block(block_published) -> dict:
""" """
Given an library block get the published data. Given an library block get the published data.
@@ -460,6 +512,17 @@ def searchable_doc_collections(opaque_key: OpaqueKey) -> dict:
return doc return doc
def searchable_doc_units(opaque_key: OpaqueKey) -> dict:
"""
Generate a dictionary document suitable for ingestion into a search engine
like Meilisearch or Elasticsearch, with the units data for the given content object.
"""
doc = searchable_doc_for_key(opaque_key)
doc.update(_units_for_content_object(opaque_key))
return doc
def searchable_doc_tags_for_collection( def searchable_doc_tags_for_collection(
collection_key: LibraryCollectionLocator collection_key: LibraryCollectionLocator
) -> dict: ) -> dict:

View File

@@ -46,6 +46,7 @@ from .api import (
upsert_content_object_tags_index_doc, upsert_content_object_tags_index_doc,
upsert_collection_tags_index_docs, upsert_collection_tags_index_docs,
upsert_item_collections_index_docs, upsert_item_collections_index_docs,
upsert_item_units_index_docs,
) )
from .tasks import ( from .tasks import (
delete_library_block_index_doc, delete_library_block_index_doc,
@@ -263,6 +264,8 @@ def content_object_associations_changed_handler(**kwargs) -> None:
upsert_content_object_tags_index_doc(opaque_key) upsert_content_object_tags_index_doc(opaque_key)
if not content_object.changes or "collections" in content_object.changes: if not content_object.changes or "collections" in content_object.changes:
upsert_item_collections_index_docs(opaque_key) upsert_item_collections_index_docs(opaque_key)
if not content_object.changes or "units" in content_object.changes:
upsert_item_units_index_docs(opaque_key)
@receiver(LIBRARY_CONTAINER_CREATED) @receiver(LIBRARY_CONTAINER_CREATED)

View File

@@ -8,7 +8,7 @@ import copy
from datetime import datetime, timezone from datetime import datetime, timezone
from unittest.mock import MagicMock, Mock, call, patch from unittest.mock import MagicMock, Mock, call, patch
from opaque_keys.edx.keys import UsageKey from opaque_keys.edx.keys import UsageKey
from opaque_keys.edx.locator import LibraryCollectionLocator from opaque_keys.edx.locator import LibraryCollectionLocator, LibraryContainerLocator
import ddt import ddt
import pytest import pytest
@@ -134,8 +134,8 @@ class TestSearchApi(ModuleStoreTestCase):
lib_access, _ = SearchAccess.objects.get_or_create(context_key=self.library.key) lib_access, _ = SearchAccess.objects.get_or_create(context_key=self.library.key)
# Populate it with 2 problems, freezing the date so we can verify created date serializes correctly. # Populate it with 2 problems, freezing the date so we can verify created date serializes correctly.
created_date = datetime(2023, 4, 5, 6, 7, 8, tzinfo=timezone.utc) self.created_date = datetime(2023, 4, 5, 6, 7, 8, tzinfo=timezone.utc)
with freeze_time(created_date): with freeze_time(self.created_date):
self.problem1 = library_api.create_library_block(self.library.key, "problem", "p1") self.problem1 = library_api.create_library_block(self.library.key, "problem", "p1")
self.problem2 = library_api.create_library_block(self.library.key, "problem", "p2") self.problem2 = library_api.create_library_block(self.library.key, "problem", "p2")
# Update problem1, freezing the date so we can verify modified date serializes correctly. # Update problem1, freezing the date so we can verify modified date serializes correctly.
@@ -155,7 +155,7 @@ class TestSearchApi(ModuleStoreTestCase):
"type": "library_block", "type": "library_block",
"access_id": lib_access.id, "access_id": lib_access.id,
"last_published": None, "last_published": None,
"created": created_date.timestamp(), "created": self.created_date.timestamp(),
"modified": modified_date.timestamp(), "modified": modified_date.timestamp(),
"publish_status": "never", "publish_status": "never",
} }
@@ -172,8 +172,8 @@ class TestSearchApi(ModuleStoreTestCase):
"type": "library_block", "type": "library_block",
"access_id": lib_access.id, "access_id": lib_access.id,
"last_published": None, "last_published": None,
"created": created_date.timestamp(), "created": self.created_date.timestamp(),
"modified": created_date.timestamp(), "modified": self.created_date.timestamp(),
"publish_status": "never", "publish_status": "never",
} }
@@ -189,7 +189,7 @@ class TestSearchApi(ModuleStoreTestCase):
# Create a collection: # Create a collection:
self.learning_package = authoring_api.get_learning_package_by_key(self.library.key) self.learning_package = authoring_api.get_learning_package_by_key(self.library.key)
with freeze_time(created_date): with freeze_time(self.created_date):
self.collection = authoring_api.create_collection( self.collection = authoring_api.create_collection(
learning_package_id=self.learning_package.id, learning_package_id=self.learning_package.id,
key="MYCOL", key="MYCOL",
@@ -210,8 +210,8 @@ class TestSearchApi(ModuleStoreTestCase):
"num_children": 0, "num_children": 0,
"context_key": "lib:org1:lib", "context_key": "lib:org1:lib",
"org": "org1", "org": "org1",
"created": created_date.timestamp(), "created": self.created_date.timestamp(),
"modified": created_date.timestamp(), "modified": self.created_date.timestamp(),
"access_id": lib_access.id, "access_id": lib_access.id,
"published": { "published": {
"num_children": 0 "num_children": 0
@@ -220,7 +220,7 @@ class TestSearchApi(ModuleStoreTestCase):
} }
# Create a unit: # Create a unit:
with freeze_time(created_date): with freeze_time(self.created_date):
self.unit = library_api.create_container( self.unit = library_api.create_container(
library_key=self.library.key, library_key=self.library.key,
container_type=library_api.ContainerType.Unit, container_type=library_api.ContainerType.Unit,
@@ -242,8 +242,8 @@ class TestSearchApi(ModuleStoreTestCase):
"publish_status": "never", "publish_status": "never",
"context_key": "lib:org1:lib", "context_key": "lib:org1:lib",
"org": "org1", "org": "org1",
"created": created_date.timestamp(), "created": self.created_date.timestamp(),
"modified": created_date.timestamp(), "modified": self.created_date.timestamp(),
"last_published": None, "last_published": None,
"access_id": lib_access.id, "access_id": lib_access.id,
"breadcrumbs": [{"display_name": "Library"}], "breadcrumbs": [{"display_name": "Library"}],
@@ -268,9 +268,11 @@ class TestSearchApi(ModuleStoreTestCase):
doc_problem1 = copy.deepcopy(self.doc_problem1) doc_problem1 = copy.deepcopy(self.doc_problem1)
doc_problem1["tags"] = {} doc_problem1["tags"] = {}
doc_problem1["collections"] = {'display_name': [], 'key': []} doc_problem1["collections"] = {'display_name': [], 'key': []}
doc_problem1["units"] = {'display_name': [], 'key': []}
doc_problem2 = copy.deepcopy(self.doc_problem2) doc_problem2 = copy.deepcopy(self.doc_problem2)
doc_problem2["tags"] = {} doc_problem2["tags"] = {}
doc_problem2["collections"] = {'display_name': [], 'key': []} doc_problem2["collections"] = {'display_name': [], 'key': []}
doc_problem2["units"] = {'display_name': [], 'key': []}
doc_collection = copy.deepcopy(self.collection_dict) doc_collection = copy.deepcopy(self.collection_dict)
doc_collection["tags"] = {} doc_collection["tags"] = {}
doc_unit = copy.deepcopy(self.unit_dict) doc_unit = copy.deepcopy(self.unit_dict)
@@ -300,9 +302,11 @@ class TestSearchApi(ModuleStoreTestCase):
doc_problem1 = copy.deepcopy(self.doc_problem1) doc_problem1 = copy.deepcopy(self.doc_problem1)
doc_problem1["tags"] = {} doc_problem1["tags"] = {}
doc_problem1["collections"] = {"display_name": [], "key": []} doc_problem1["collections"] = {"display_name": [], "key": []}
doc_problem1["units"] = {'display_name': [], 'key': []}
doc_problem2 = copy.deepcopy(self.doc_problem2) doc_problem2 = copy.deepcopy(self.doc_problem2)
doc_problem2["tags"] = {} doc_problem2["tags"] = {}
doc_problem2["collections"] = {"display_name": [], "key": []} doc_problem2["collections"] = {"display_name": [], "key": []}
doc_problem2["units"] = {'display_name': [], 'key': []}
doc_collection = copy.deepcopy(self.collection_dict) doc_collection = copy.deepcopy(self.collection_dict)
doc_collection["tags"] = {} doc_collection["tags"] = {}
doc_unit = copy.deepcopy(self.unit_dict) doc_unit = copy.deepcopy(self.unit_dict)
@@ -417,6 +421,7 @@ class TestSearchApi(ModuleStoreTestCase):
doc_problem2 = copy.deepcopy(self.doc_problem2) doc_problem2 = copy.deepcopy(self.doc_problem2)
doc_problem2["tags"] = {} doc_problem2["tags"] = {}
doc_problem2["collections"] = {'display_name': [], 'key': []} doc_problem2["collections"] = {'display_name': [], 'key': []}
doc_problem2["units"] = {'display_name': [], 'key': []}
orig_from_component = library_api.LibraryXBlockMetadata.from_component orig_from_component = library_api.LibraryXBlockMetadata.from_component
@@ -939,3 +944,34 @@ class TestSearchApi(ModuleStoreTestCase):
], ],
any_order=True, any_order=True,
) )
@override_settings(MEILISEARCH_ENABLED=True)
def test_block_in_units(self, mock_meilisearch):
with freeze_time(self.created_date):
library_api.update_container_children(
LibraryContainerLocator.from_string(self.unit_key),
[self.problem1.usage_key],
None,
)
doc_block_with_units = {
"id": self.doc_problem1["id"],
"units": {
"display_name": [self.unit.display_name],
"key": [self.unit_key],
},
}
new_unit_dict = {
**self.unit_dict,
"num_children": 1,
'content': {'child_usage_keys': [self.doc_problem1["usage_key"]]}
}
assert mock_meilisearch.return_value.index.return_value.update_documents.call_count == 2
mock_meilisearch.return_value.index.return_value.update_documents.assert_has_calls(
[
call([doc_block_with_units]),
call([new_unit_dict]),
],
any_order=True,
)

View File

@@ -646,11 +646,11 @@ def restore_library_block(usage_key: LibraryUsageLocatorV2, user_id: int | None
) )
) )
# Add tags and collections back to index # Add tags, collections and units back to index
CONTENT_OBJECT_ASSOCIATIONS_CHANGED.send_event( CONTENT_OBJECT_ASSOCIATIONS_CHANGED.send_event(
content_object=ContentObjectChangedData( content_object=ContentObjectChangedData(
object_id=str(usage_key), object_id=str(usage_key),
changes=["collections", "tags"], changes=["collections", "tags", "units"],
), ),
) )

View File

@@ -429,6 +429,14 @@ def update_container_children(
created_by=user_id, created_by=user_id,
entities_action=entities_action, entities_action=entities_action,
) )
for key in children_ids:
CONTENT_OBJECT_ASSOCIATIONS_CHANGED.send_event(
content_object=ContentObjectChangedData(
object_id=str(key),
changes=["units"],
),
)
case _: case _:
raise ValueError(f"Invalid container type: {container_type}") raise ValueError(f"Invalid container type: {container_type}")

View File

@@ -839,6 +839,83 @@ class ContentLibraryContainersTest(ContentLibrariesRestApiTest):
self._set_library_block_fields(self.html_block_usage_key, {"data": block_olx, "metadata": {}}) self._set_library_block_fields(self.html_block_usage_key, {"data": block_olx, "metadata": {}})
self._validate_calls_of_html_block(container_update_event_receiver) self._validate_calls_of_html_block(container_update_event_receiver)
def test_call_object_changed_signal_when_remove_component(self):
html_block_1 = self._add_block_to_library(
self.lib1.library_key, "html", "html3",
)
api.update_container_children(
self.unit2.container_key,
[UsageKey.from_string(html_block_1["id"])],
None,
entities_action=authoring_api.ChildrenEntitiesAction.APPEND,
)
event_reciver = mock.Mock()
CONTENT_OBJECT_ASSOCIATIONS_CHANGED.connect(event_reciver)
api.update_container_children(
self.unit2.container_key,
[UsageKey.from_string(html_block_1["id"])],
None,
entities_action=authoring_api.ChildrenEntitiesAction.REMOVE,
)
assert event_reciver.call_count == 1
self.assertDictContainsSubset(
{
"signal": CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
"sender": None,
"content_object": ContentObjectChangedData(
object_id=html_block_1["id"],
changes=["units"],
),
},
event_reciver.call_args_list[0].kwargs,
)
def test_call_object_changed_signal_when_add_component(self):
event_reciver = mock.Mock()
CONTENT_OBJECT_ASSOCIATIONS_CHANGED.connect(event_reciver)
html_block_1 = self._add_block_to_library(
self.lib1.library_key, "html", "html4",
)
html_block_2 = self._add_block_to_library(
self.lib1.library_key, "html", "html5",
)
api.update_container_children(
self.unit2.container_key,
[
UsageKey.from_string(html_block_1["id"]),
UsageKey.from_string(html_block_2["id"])
],
None,
entities_action=authoring_api.ChildrenEntitiesAction.APPEND,
)
assert event_reciver.call_count == 2
self.assertDictContainsSubset(
{
"signal": CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
"sender": None,
"content_object": ContentObjectChangedData(
object_id=html_block_1["id"],
changes=["units"],
),
},
event_reciver.call_args_list[0].kwargs,
)
self.assertDictContainsSubset(
{
"signal": CONTENT_OBJECT_ASSOCIATIONS_CHANGED,
"sender": None,
"content_object": ContentObjectChangedData(
object_id=html_block_2["id"],
changes=["units"],
),
},
event_reciver.call_args_list[1].kwargs,
)
def test_delete_component_and_revert(self): def test_delete_component_and_revert(self):
""" """
When a component is deleted and then the delete is reverted, signals When a component is deleted and then the delete is reverted, signals

View File

@@ -57,13 +57,6 @@ django-stubs<6
# for them. # for them.
edx-enterprise==5.13.7 edx-enterprise==5.13.7
# Date: 2024-07-26
# To override the constraint of edx-lint
# This can be removed once https://github.com/openedx/edx-platform/issues/34586 is resolved
# and the upstream constraint in edx-lint has been removed.
# Issue for unpinning: https://github.com/openedx/edx-platform/issues/35273
event-tracking==3.0.0
# Date: 2023-07-26 # Date: 2023-07-26
# Our legacy Sass code is incompatible with anything except this ancient libsass version. # Our legacy Sass code is incompatible with anything except this ancient libsass version.
# Here is a ticket to upgrade, but it's of debatable importance given that we are rapidly moving # Here is a ticket to upgrade, but it's of debatable importance given that we are rapidly moving

View File

@@ -546,9 +546,8 @@ enmerkar==0.7.1
# via enmerkar-underscore # via enmerkar-underscore
enmerkar-underscore==2.4.0 enmerkar-underscore==2.4.0
# via -r requirements/edx/kernel.in # via -r requirements/edx/kernel.in
event-tracking==3.0.0 event-tracking==3.3.0
# via # via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/kernel.in # -r requirements/edx/kernel.in
# edx-completion # edx-completion
# edx-proctoring # edx-proctoring

View File

@@ -860,9 +860,8 @@ enmerkar-underscore==2.4.0
# via # via
# -r requirements/edx/doc.txt # -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt # -r requirements/edx/testing.txt
event-tracking==3.0.0 event-tracking==3.3.0
# via # via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/doc.txt # -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt # -r requirements/edx/testing.txt
# edx-completion # edx-completion

View File

@@ -637,9 +637,8 @@ enmerkar==0.7.1
# enmerkar-underscore # enmerkar-underscore
enmerkar-underscore==2.4.0 enmerkar-underscore==2.4.0
# via -r requirements/edx/base.txt # via -r requirements/edx/base.txt
event-tracking==3.0.0 event-tracking==3.3.0
# via # via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt # -r requirements/edx/base.txt
# edx-completion # edx-completion
# edx-proctoring # edx-proctoring

View File

@@ -664,9 +664,8 @@ enmerkar==0.7.1
# enmerkar-underscore # enmerkar-underscore
enmerkar-underscore==2.4.0 enmerkar-underscore==2.4.0
# via -r requirements/edx/base.txt # via -r requirements/edx/base.txt
event-tracking==3.0.0 event-tracking==3.3.0
# via # via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt # -r requirements/edx/base.txt
# edx-completion # edx-completion
# edx-proctoring # edx-proctoring

View File

@@ -3399,7 +3399,7 @@ class ImageResponse(LoncapaResponse):
parsed_region = [parsed_region] parsed_region = [parsed_region]
for region in parsed_region: for region in parsed_region:
polygon = MultiPoint(region).convex_hull polygon = MultiPoint(region).convex_hull
if (polygon.type == 'Polygon' and if (polygon.geom_type == 'Polygon' and
polygon.contains(Point(ans_x, ans_y))): polygon.contains(Point(ans_x, ans_y))):
correct_map.set(aid, 'correct') correct_map.set(aid, 'correct')
break break

View File

@@ -58,10 +58,9 @@ class StubXQueueService:
return dispatch return dispatch
def test_capa_system(render_template=None): def mock_capa_system(render_template=None):
""" """
Construct a mock LoncapaSystem instance. Construct a mock LoncapaSystem instance.
""" """
the_system = Mock( the_system = Mock(
spec=LoncapaSystem, spec=LoncapaSystem,
@@ -102,7 +101,7 @@ def mock_capa_block():
def new_loncapa_problem(xml, problem_id='1', capa_system=None, seed=723, use_capa_render_template=False): def new_loncapa_problem(xml, problem_id='1', capa_system=None, seed=723, use_capa_render_template=False):
"""Construct a `LoncapaProblem` suitable for unit tests.""" """Construct a `LoncapaProblem` suitable for unit tests."""
render_template = capa_render_template if use_capa_render_template else None render_template = capa_render_template if use_capa_render_template else None
return LoncapaProblem(xml, id=problem_id, seed=seed, capa_system=capa_system or test_capa_system(render_template), return LoncapaProblem(xml, id=problem_id, seed=seed, capa_system=capa_system or mock_capa_system(render_template),
capa_block=mock_capa_block()) capa_block=mock_capa_block())

View File

@@ -8,7 +8,7 @@ import textwrap
import unittest import unittest
from xmodule.capa.responsetypes import LoncapaProblemError from xmodule.capa.responsetypes import LoncapaProblemError
from xmodule.capa.tests.helpers import new_loncapa_problem, test_capa_system from xmodule.capa.tests.helpers import new_loncapa_problem, mock_capa_system
class CapaAnswerPoolTest(unittest.TestCase): class CapaAnswerPoolTest(unittest.TestCase):
@@ -16,7 +16,7 @@ class CapaAnswerPoolTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(CapaAnswerPoolTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments super(CapaAnswerPoolTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
self.system = test_capa_system() self.system = mock_capa_system()
# XML problem setup used by a few tests. # XML problem setup used by a few tests.
common_question_xml = textwrap.dedent(""" common_question_xml = textwrap.dedent("""

View File

@@ -6,7 +6,7 @@ import xml.sax.saxutils as saxutils
from lxml import etree from lxml import etree
from xmodule.capa import customrender from xmodule.capa import customrender
from xmodule.capa.tests.helpers import test_capa_system from xmodule.capa.tests.helpers import mock_capa_system
# just a handy shortcut # just a handy shortcut
lookup_tag = customrender.registry.get_class_for_tag lookup_tag = customrender.registry.get_class_for_tag
@@ -30,7 +30,7 @@ class HelperTest(unittest.TestCase):
''' '''
def check(self, d): def check(self, d):
xml = etree.XML(test_capa_system().render_template('blah', d)) xml = etree.XML(mock_capa_system().render_template('blah', d))
assert d == extract_context(xml) assert d == extract_context(xml)
def test_extract_context(self): def test_extract_context(self):
@@ -50,7 +50,7 @@ class SolutionRenderTest(unittest.TestCase):
xml_str = """<solution id="solution_12">{s}</solution>""".format(s=solution) xml_str = """<solution id="solution_12">{s}</solution>""".format(s=solution)
element = etree.fromstring(xml_str) element = etree.fromstring(xml_str)
renderer = lookup_tag('solution')(test_capa_system(), element) renderer = lookup_tag('solution')(mock_capa_system(), element)
assert renderer.id == 'solution_12' assert renderer.id == 'solution_12'
@@ -69,7 +69,7 @@ class MathRenderTest(unittest.TestCase):
xml_str = """<math>{tex}</math>""".format(tex=latex_in) xml_str = """<math>{tex}</math>""".format(tex=latex_in)
element = etree.fromstring(xml_str) element = etree.fromstring(xml_str)
renderer = lookup_tag('math')(test_capa_system(), element) renderer = lookup_tag('math')(mock_capa_system(), element)
assert renderer.mathstr == mathjax_out assert renderer.mathstr == mathjax_out

View File

@@ -10,7 +10,7 @@ from unittest import mock
import ddt import ddt
from lxml import etree from lxml import etree
from xmodule.capa.tests.helpers import new_loncapa_problem, test_capa_system from xmodule.capa.tests.helpers import new_loncapa_problem, mock_capa_system
from openedx.core.djangolib.markup import HTML from openedx.core.djangolib.markup import HTML
from .response_xml_factory import CustomResponseXMLFactory, StringResponseXMLFactory from .response_xml_factory import CustomResponseXMLFactory, StringResponseXMLFactory
@@ -24,7 +24,7 @@ class CapaHtmlRenderTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(CapaHtmlRenderTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments super(CapaHtmlRenderTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
self.capa_system = test_capa_system() self.capa_system = mock_capa_system()
def test_blank_problem(self): def test_blank_problem(self):
""" """
@@ -148,7 +148,7 @@ class CapaHtmlRenderTest(unittest.TestCase):
xml_str = StringResponseXMLFactory().build_xml(**kwargs) xml_str = StringResponseXMLFactory().build_xml(**kwargs)
# Mock out the template renderer # Mock out the template renderer
the_system = test_capa_system() the_system = mock_capa_system()
the_system.render_template = mock.Mock() the_system.render_template = mock.Mock()
the_system.render_template.return_value = "<div class='input-template-render'>Input Template Render</div>" the_system.render_template.return_value = "<div class='input-template-render'>Input Template Render</div>"

View File

@@ -34,7 +34,7 @@ from six.moves import zip
from xmodule.capa import inputtypes from xmodule.capa import inputtypes
from xmodule.capa.checker import DemoSystem from xmodule.capa.checker import DemoSystem
from xmodule.capa.tests.helpers import test_capa_system from xmodule.capa.tests.helpers import mock_capa_system
from xmodule.capa.xqueue_interface import XQUEUE_TIMEOUT from xmodule.capa.xqueue_interface import XQUEUE_TIMEOUT
from openedx.core.djangolib.markup import HTML from openedx.core.djangolib.markup import HTML
@@ -72,7 +72,7 @@ class OptionInputTest(unittest.TestCase):
'default_option_text': 'Select an option', 'default_option_text': 'Select an option',
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
option_input = lookup_tag('optioninput')(test_capa_system(), element, state) option_input = lookup_tag('optioninput')(mock_capa_system(), element, state)
context = option_input._get_render_context() # pylint: disable=protected-access context = option_input._get_render_context() # pylint: disable=protected-access
prob_id = 'sky_input' prob_id = 'sky_input'
@@ -138,7 +138,7 @@ class ChoiceGroupTest(unittest.TestCase):
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag(tag)(test_capa_system(), element, state) the_input = lookup_tag(tag)(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
@@ -233,7 +233,7 @@ class JSInputTest(unittest.TestCase):
'value': 103, 'value': 103,
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('jsinput')(test_capa_system(), element, state) the_input = lookup_tag('jsinput')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
@@ -270,7 +270,7 @@ class TextLineTest(unittest.TestCase):
'value': 'BumbleBee', 'value': 'BumbleBee',
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('textline')(test_capa_system(), element, state) the_input = lookup_tag('textline')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -306,7 +306,7 @@ class TextLineTest(unittest.TestCase):
'value': 'BumbleBee', 'value': 'BumbleBee',
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('textline')(test_capa_system(), element, state) the_input = lookup_tag('textline')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -354,7 +354,7 @@ class TextLineTest(unittest.TestCase):
'value': 'BumbleBee', 'value': 'BumbleBee',
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('textline')(test_capa_system(), element, state) the_input = lookup_tag('textline')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -400,7 +400,7 @@ class FileSubmissionTest(unittest.TestCase):
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
input_class = lookup_tag('filesubmission') input_class = lookup_tag('filesubmission')
the_input = input_class(test_capa_system(), element, state) the_input = input_class(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -450,7 +450,7 @@ class CodeInputTest(unittest.TestCase):
} }
input_class = lookup_tag('codeinput') input_class = lookup_tag('codeinput')
the_input = input_class(test_capa_system(), element, state) the_input = input_class(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -510,7 +510,7 @@ class MatlabTest(unittest.TestCase):
} }
self.input_class = lookup_tag('matlabinput') self.input_class = lookup_tag('matlabinput')
self.the_input = self.input_class(test_capa_system(), elt, state) self.the_input = self.input_class(mock_capa_system(), elt, state)
def test_rendering(self): def test_rendering(self):
context = self.the_input._get_render_context() # pylint: disable=protected-access context = self.the_input._get_render_context() # pylint: disable=protected-access
@@ -547,7 +547,7 @@ class MatlabTest(unittest.TestCase):
} }
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
expected = { expected = {
@@ -582,7 +582,7 @@ class MatlabTest(unittest.TestCase):
} }
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
expected = { expected = {
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
@@ -616,7 +616,7 @@ class MatlabTest(unittest.TestCase):
} }
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
expected = { expected = {
'STATIC_URL': '/dummy-static/', 'STATIC_URL': '/dummy-static/',
@@ -668,7 +668,7 @@ class MatlabTest(unittest.TestCase):
'feedback': {'message': '3'}, } 'feedback': {'message': '3'}, }
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
inner_msg = 'hello!' inner_msg = 'hello!'
queue_msg = json.dumps({'msg': inner_msg}) queue_msg = json.dumps({'msg': inner_msg})
@@ -687,7 +687,7 @@ class MatlabTest(unittest.TestCase):
'feedback': {'message': '3'}, } 'feedback': {'message': '3'}, }
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
inner_msg = 'hello!' inner_msg = 'hello!'
queue_msg = json.dumps({'msg': inner_msg}) queue_msg = json.dumps({'msg': inner_msg})
@@ -702,7 +702,7 @@ class MatlabTest(unittest.TestCase):
state = {'input_state': {'queuestate': 'queued', 'queuetime': 5}} state = {'input_state': {'queuestate': 'queued', 'queuetime': 5}}
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
assert the_input.status == 'queued' assert the_input.status == 'queued'
@patch('xmodule.capa.inputtypes.time.time', return_value=45) @patch('xmodule.capa.inputtypes.time.time', return_value=45)
@@ -711,7 +711,7 @@ class MatlabTest(unittest.TestCase):
state = {'input_state': {'queuestate': 'queued', 'queuetime': 5}} state = {'input_state': {'queuestate': 'queued', 'queuetime': 5}}
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
assert the_input.status == 'unsubmitted' assert the_input.status == 'unsubmitted'
assert the_input.msg == 'No response from Xqueue within {} seconds. Aborted.'.format(XQUEUE_TIMEOUT) assert the_input.msg == 'No response from Xqueue within {} seconds. Aborted.'.format(XQUEUE_TIMEOUT)
@@ -723,7 +723,7 @@ class MatlabTest(unittest.TestCase):
state = {'input_state': {'queuestate': 'queued'}} state = {'input_state': {'queuestate': 'queued'}}
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
assert the_input.status == 'unsubmitted' assert the_input.status == 'unsubmitted'
def test_matlab_api_key(self): def test_matlab_api_key(self):
@@ -731,7 +731,7 @@ class MatlabTest(unittest.TestCase):
Test that api_key ends up in the xqueue payload Test that api_key ends up in the xqueue payload
""" """
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
system = test_capa_system() system = mock_capa_system()
system.matlab_api_key = 'test_api_key' system.matlab_api_key = 'test_api_key'
the_input = lookup_tag('matlabinput')(system, elt, {}) the_input = lookup_tag('matlabinput')(system, elt, {})
@@ -852,7 +852,7 @@ class MatlabTest(unittest.TestCase):
} }
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
self.maxDiff = None self.maxDiff = None
expected = fromstring('\n<div class="matlabResponse"><div class="commandWindowOutput" style="white-space: pre;"> <strong>if</strong> Conditionally execute statements.\nThe general form of the <strong>if</strong> statement is\n\n <strong>if</strong> expression\n statements\n ELSEIF expression\n statements\n ELSE\n statements\n END\n\nThe statements are executed if the real part of the expression \nhas all non-zero elements. The ELSE and ELSEIF parts are optional.\nZero or more ELSEIF parts can be used as well as nested <strong>if</strong>\'s.\nThe expression is usually of the form expr rop expr where \nrop is ==, &lt;, &gt;, &lt;=, &gt;=, or ~=.\n<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjAAAAGkCAIAAACgj==">\n\nExample\n if I == J\n A(I,J) = 2;\n elseif abs(I-J) == 1\n A(I,J) = -1;\n else\n A(I,J) = 0;\n end\n\nSee also <a>relop</a>, <a>else</a>, <a>elseif</a>, <a>end</a>, <a>for</a>, <a>while</a>, <a>switch</a>.\n\nReference page in Help browser\n <a>doc if</a>\n\n</div><ul></ul></div>\n') # lint-amnesty, pylint: disable=line-too-long expected = fromstring('\n<div class="matlabResponse"><div class="commandWindowOutput" style="white-space: pre;"> <strong>if</strong> Conditionally execute statements.\nThe general form of the <strong>if</strong> statement is\n\n <strong>if</strong> expression\n statements\n ELSEIF expression\n statements\n ELSE\n statements\n END\n\nThe statements are executed if the real part of the expression \nhas all non-zero elements. The ELSE and ELSEIF parts are optional.\nZero or more ELSEIF parts can be used as well as nested <strong>if</strong>\'s.\nThe expression is usually of the form expr rop expr where \nrop is ==, &lt;, &gt;, &lt;=, &gt;=, or ~=.\n<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAjAAAAGkCAIAAACgj==">\n\nExample\n if I == J\n A(I,J) = 2;\n elseif abs(I-J) == 1\n A(I,J) = -1;\n else\n A(I,J) = 0;\n end\n\nSee also <a>relop</a>, <a>else</a>, <a>elseif</a>, <a>end</a>, <a>for</a>, <a>while</a>, <a>switch</a>.\n\nReference page in Help browser\n <a>doc if</a>\n\n</div><ul></ul></div>\n') # lint-amnesty, pylint: disable=line-too-long
@@ -901,7 +901,7 @@ class MatlabTest(unittest.TestCase):
'status': 'queued', 'status': 'queued',
} }
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
assert the_input.queue_msg == queue_msg assert the_input.queue_msg == queue_msg
def test_matlab_queue_message_not_allowed_tag(self): def test_matlab_queue_message_not_allowed_tag(self):
@@ -915,7 +915,7 @@ class MatlabTest(unittest.TestCase):
'status': 'queued', 'status': 'queued',
} }
elt = etree.fromstring(self.xml) elt = etree.fromstring(self.xml)
the_input = self.input_class(test_capa_system(), elt, state) the_input = self.input_class(mock_capa_system(), elt, state)
expected = "" expected = ""
assert the_input.queue_msg == expected assert the_input.queue_msg == expected
@@ -974,7 +974,7 @@ class SchematicTest(unittest.TestCase):
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('schematic')(test_capa_system(), element, state) the_input = lookup_tag('schematic')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -1021,7 +1021,7 @@ class ImageInputTest(unittest.TestCase):
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('imageinput')(test_capa_system(), element, state) the_input = lookup_tag('imageinput')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -1079,7 +1079,7 @@ class CrystallographyTest(unittest.TestCase):
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('crystallography')(test_capa_system(), element, state) the_input = lookup_tag('crystallography')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -1124,7 +1124,7 @@ class VseprTest(unittest.TestCase):
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('vsepr_input')(test_capa_system(), element, state) the_input = lookup_tag('vsepr_input')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -1160,7 +1160,7 @@ class ChemicalEquationTest(unittest.TestCase):
'value': 'H2OYeah', 'value': 'H2OYeah',
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
self.the_input = lookup_tag('chemicalequationinput')(test_capa_system(), element, state) self.the_input = lookup_tag('chemicalequationinput')(mock_capa_system(), element, state)
def test_rendering(self): def test_rendering(self):
""" """
@@ -1255,7 +1255,7 @@ class FormulaEquationTest(unittest.TestCase):
'value': 'x^2+1/2', 'value': 'x^2+1/2',
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
self.the_input = lookup_tag('formulaequationinput')(test_capa_system(), element, state) self.the_input = lookup_tag('formulaequationinput')(mock_capa_system(), element, state)
def test_rendering(self): def test_rendering(self):
""" """
@@ -1305,7 +1305,7 @@ class FormulaEquationTest(unittest.TestCase):
'value': 'x^2+1/2', 'value': 'x^2+1/2',
'response_data': RESPONSE_DATA 'response_data': RESPONSE_DATA
} }
the_input = lookup_tag('formulaequationinput')(test_capa_system(), element, state) the_input = lookup_tag('formulaequationinput')(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
@@ -1440,7 +1440,7 @@ class DragAndDropTest(unittest.TestCase):
] ]
} }
the_input = lookup_tag('drag_and_drop_input')(test_capa_system(), element, state) the_input = lookup_tag('drag_and_drop_input')(mock_capa_system(), element, state)
prob_id = 'prob_1_2' prob_id = 'prob_1_2'
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
expected = { expected = {
@@ -1494,7 +1494,7 @@ class AnnotationInputTest(unittest.TestCase):
tag = 'annotationinput' tag = 'annotationinput'
the_input = lookup_tag(tag)(test_capa_system(), element, state) the_input = lookup_tag(tag)(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
prob_id = 'annotation_input' prob_id = 'annotation_input'
@@ -1588,7 +1588,7 @@ class TestChoiceText(unittest.TestCase):
'describedby_html': DESCRIBEDBY.format(status_id=prob_id) 'describedby_html': DESCRIBEDBY.format(status_id=prob_id)
} }
expected.update(state) expected.update(state)
the_input = lookup_tag(tag)(test_capa_system(), element, state) the_input = lookup_tag(tag)(mock_capa_system(), element, state)
context = the_input._get_render_context() # pylint: disable=protected-access context = the_input._get_render_context() # pylint: disable=protected-access
assert context == expected assert context == expected

View File

@@ -20,7 +20,7 @@ from pytz import UTC
from xmodule.capa.correctmap import CorrectMap from xmodule.capa.correctmap import CorrectMap
from xmodule.capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError from xmodule.capa.responsetypes import LoncapaProblemError, ResponseError, StudentInputError
from xmodule.capa.tests.helpers import load_fixture, new_loncapa_problem, test_capa_system from xmodule.capa.tests.helpers import load_fixture, new_loncapa_problem, mock_capa_system
from xmodule.capa.tests.response_xml_factory import ( from xmodule.capa.tests.response_xml_factory import (
AnnotationResponseXMLFactory, AnnotationResponseXMLFactory,
ChoiceResponseXMLFactory, ChoiceResponseXMLFactory,
@@ -2326,7 +2326,7 @@ class CustomResponseTest(ResponseTest): # pylint: disable=missing-class-docstri
import my_helper import my_helper
num = my_helper.seventeen() num = my_helper.seventeen()
""") """)
capa_system = test_capa_system() capa_system = mock_capa_system()
capa_system.get_python_lib_zip = lambda: zipstring.getvalue() # lint-amnesty, pylint: disable=unnecessary-lambda capa_system.get_python_lib_zip = lambda: zipstring.getvalue() # lint-amnesty, pylint: disable=unnecessary-lambda
problem = self.build_problem(script=script, capa_system=capa_system) problem = self.build_problem(script=script, capa_system=capa_system)
assert problem.context['num'] == 17 assert problem.context['num'] == 17

View File

@@ -5,7 +5,7 @@ import textwrap
import unittest import unittest
from xmodule.capa.responsetypes import LoncapaProblemError from xmodule.capa.responsetypes import LoncapaProblemError
from xmodule.capa.tests.helpers import new_loncapa_problem, test_capa_system from xmodule.capa.tests.helpers import new_loncapa_problem, mock_capa_system
class CapaShuffleTest(unittest.TestCase): class CapaShuffleTest(unittest.TestCase):
@@ -13,7 +13,7 @@ class CapaShuffleTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(CapaShuffleTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments super(CapaShuffleTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
self.system = test_capa_system() self.system = mock_capa_system()
def test_shuffle_4_choices(self): def test_shuffle_4_choices(self):
xml_str = textwrap.dedent(""" xml_str = textwrap.dedent("""

View File

@@ -6,7 +6,7 @@ i.e. those with the <multiplechoiceresponse> element
import textwrap import textwrap
import unittest import unittest
from xmodule.capa.tests.helpers import load_fixture, new_loncapa_problem, test_capa_system from xmodule.capa.tests.helpers import load_fixture, new_loncapa_problem, mock_capa_system
class CapaTargetedFeedbackTest(unittest.TestCase): class CapaTargetedFeedbackTest(unittest.TestCase):
@@ -16,7 +16,7 @@ class CapaTargetedFeedbackTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(CapaTargetedFeedbackTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments super(CapaTargetedFeedbackTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
self.system = test_capa_system() self.system = mock_capa_system()
def test_no_targeted_feedback(self): def test_no_targeted_feedback(self):
xml_str = textwrap.dedent(""" xml_str = textwrap.dedent("""

View File

@@ -9,7 +9,7 @@ import unittest
import ddt import ddt
from lxml import etree from lxml import etree
from xmodule.capa.tests.helpers import test_capa_system from xmodule.capa.tests.helpers import mock_capa_system
from xmodule.capa.util import ( from xmodule.capa.util import (
compare_with_tolerance, compare_with_tolerance,
contextualize_text, contextualize_text,
@@ -25,7 +25,7 @@ class UtilTest(unittest.TestCase):
def setUp(self): def setUp(self):
super(UtilTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments super(UtilTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
self.system = test_capa_system() self.system = mock_capa_system()
def test_compare_with_tolerance(self): # lint-amnesty, pylint: disable=too-many-statements def test_compare_with_tolerance(self): # lint-amnesty, pylint: disable=too-many-statements
# Test default tolerance '0.001%' (it is relative) # Test default tolerance '0.001%' (it is relative)

View File

@@ -2798,48 +2798,6 @@ class ProblemBlockTest(unittest.TestCase): # lint-amnesty, pylint: disable=miss
('shuffle', ['choice_3', 'choice_1', 'choice_2', 'choice_0']) ('shuffle', ['choice_3', 'choice_1', 'choice_2', 'choice_0'])
assert event_info['success'] == 'correct' assert event_info['success'] == 'correct'
@unittest.skip("masking temporarily disabled")
def test_save_unmask(self):
"""On problem save, unmasked data should appear on publish."""
block = CapaFactory.create(xml=self.common_shuffle_xml)
with patch.object(block.runtime, 'publish') as mock_publish:
get_request_dict = {CapaFactory.input_key(): 'mask_0'}
block.save_problem(get_request_dict)
mock_call = mock_publish.mock_calls[0]
event_info = mock_call[1][1]
assert event_info['answers'][CapaFactory.answer_key()] == 'choice_2'
assert event_info['permutation'][CapaFactory.answer_key()] is not None
@unittest.skip("masking temporarily disabled")
def test_reset_unmask(self):
"""On problem reset, unmask names should appear publish."""
block = CapaFactory.create(xml=self.common_shuffle_xml)
get_request_dict = {CapaFactory.input_key(): 'mask_0'}
block.submit_problem(get_request_dict)
# On reset, 'old_state' should use unmasked names
with patch.object(block.runtime, 'publish') as mock_publish:
block.reset_problem(None)
mock_call = mock_publish.mock_calls[0]
event_info = mock_call[1][1]
assert mock_call[1][0] == 'reset_problem'
assert event_info['old_state']['student_answers'][CapaFactory.answer_key()] == 'choice_2'
assert event_info['permutation'][CapaFactory.answer_key()] is not None
@unittest.skip("masking temporarily disabled")
def test_rescore_unmask(self):
"""On problem rescore, unmasked names should appear on publish."""
block = CapaFactory.create(xml=self.common_shuffle_xml)
get_request_dict = {CapaFactory.input_key(): 'mask_0'}
block.submit_problem(get_request_dict)
# On rescore, state/student_answers should use unmasked names
with patch.object(block.runtime, 'publish') as mock_publish:
block.rescore_problem(only_if_higher=False) # lint-amnesty, pylint: disable=no-member
mock_call = mock_publish.mock_calls[0]
event_info = mock_call[1][1]
assert mock_call[1][0] == 'problem_rescore'
assert event_info['state']['student_answers'][CapaFactory.answer_key()] == 'choice_2'
assert event_info['permutation'][CapaFactory.answer_key()] is not None
def test_check_unmask_answerpool(self): def test_check_unmask_answerpool(self):
"""Check answer-pool question publish uses unmasked names""" """Check answer-pool question publish uses unmasked names"""
xml = textwrap.dedent(""" xml = textwrap.dedent("""