From e5485853ed445c1c258302a3043a152005b56372 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Thu, 20 Mar 2025 17:45:50 -0500 Subject: [PATCH 01/10] feat: Added get_containers_contains_component in containers api with tests --- .../content_libraries/api/containers.py | 19 +++++ .../content_libraries/tests/test_api.py | 74 +++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/openedx/core/djangoapps/content_libraries/api/containers.py b/openedx/core/djangoapps/content_libraries/api/containers.py index 6719c07065e4..c03cee2b84d8 100644 --- a/openedx/core/djangoapps/content_libraries/api/containers.py +++ b/openedx/core/djangoapps/content_libraries/api/containers.py @@ -13,6 +13,7 @@ LibraryContainerLocator, LibraryLocatorV2, UsageKeyV2, + LibraryUsageLocatorV2, ) from openedx_events.content_authoring.data import LibraryContainerData from openedx_events.content_authoring.signals import ( @@ -42,6 +43,7 @@ "update_container", "delete_container", "update_container_children", + "get_containers_contains_component", ] @@ -316,3 +318,20 @@ def update_container_children( ) return ContainerMetadata.from_container(library_key, new_version.container) + + +def get_containers_contains_component( + usage_key: LibraryUsageLocatorV2 +) -> list[ContainerMetadata]: + """ + Get containers that contains the component. + """ + assert isinstance(usage_key, LibraryUsageLocatorV2) + component = get_component_from_usage_key(usage_key) + containers = authoring_api.get_containers_with_entity( + component.publishable_entity.pk, + ) + return [ + ContainerMetadata.from_container(usage_key.context_key, container) + for container in containers + ] diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py index d4be6fdf6bd9..9e6442b96eff 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_api.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py @@ -5,6 +5,7 @@ import base64 import hashlib from unittest import mock +from datetime import datetime, timezone from django.test import TestCase @@ -742,3 +743,76 @@ def test_delete_component_and_revert(self): }, event_receiver.call_args_list[1].kwargs, ) + + +class ContentLibraryContainersTest(ContentLibrariesRestApiTest, TestCase): + """ + Tests for Content Library API containers methods. + """ + def setUp(self): + super().setUp() + + # Create Content Libraries + self._create_library("test-lib-cont-1", "Test Library 1") + + # Fetch the created ContentLibrare objects so we can access their learning_package.id + self.lib1 = ContentLibrary.objects.get(slug="test-lib-cont-1") + + # Create Units + self.unit1 = api.create_container(self.lib1.library_key, api.ContainerType.Unit, 'unit-1', 'Unit 1', None) + self.unit2 = api.create_container(self.lib1.library_key, api.ContainerType.Unit, 'unit-2', 'Unit 2', None) + + # Create XBlocks + # Create some library blocks in lib1 + self.problem_block_dict = self._add_block_to_library( + self.lib1.library_key, "problem", "problem1", + ) + self.problem_block_usage_key = UsageKey.from_string(self.problem_block_dict["id"]) + self.html_block_dict = self._add_block_to_library( + self.lib1.library_key, "html", "html1", + ) + self.html_block_usage_key = UsageKey.from_string(self.html_block_dict["id"]) + now = datetime.now(tz=timezone.utc) + + # Add content to units + # TODO build API for this + self.problem_block_component = api.get_component_from_usage_key(self.problem_block_usage_key) + self.html_block_component = api.get_component_from_usage_key(self.html_block_usage_key) + self.unit1_container = authoring_api.get_container_by_key( + self.lib1.learning_package.id, + self.unit1.container_key.container_id, + ) + self.unit2_container = authoring_api.get_container_by_key( + self.lib1.learning_package.id, + self.unit2.container_key.container_id, + ) + authoring_api.create_next_container_version( + self.unit1_container.pk, + publishable_entities_pks=[ + self.problem_block_component.publishable_entity.id, + self.html_block_component.publishable_entity.id, + ], + title=None, + entity_version_pks=None, + created=now, + created_by=None, + ) + authoring_api.create_next_container_version( + self.unit2_container.pk, + publishable_entities_pks=[self.html_block_component.publishable_entity.id], + title=None, + entity_version_pks=None, + created=now, + created_by=None, + ) + + def test_get_containers_contains_component(self): + problem_block_containers = api.get_containers_contains_component(self.problem_block_usage_key) + html_block_containers = api.get_containers_contains_component(self.html_block_usage_key) + + assert len(problem_block_containers) == 1 + assert problem_block_containers[0].container_key == self.unit1.container_key + + assert len(html_block_containers) == 2 + assert html_block_containers[0].container_key == self.unit1.container_key + assert html_block_containers[1].container_key == self.unit2.container_key From 5f0163886b6056b8cacd4d67f4ae535f993dcb43 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Fri, 21 Mar 2025 19:05:13 -0500 Subject: [PATCH 02/10] feat: Add publish_status to containers search document --- .../content/search/tests/test_documents.py | 3 +++ .../djangoapps/content_libraries/api/containers.py | 4 +++- .../djangoapps/content_libraries/tests/test_api.py | 12 ++---------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/openedx/core/djangoapps/content/search/tests/test_documents.py b/openedx/core/djangoapps/content/search/tests/test_documents.py index a2964436d039..ee2253347f20 100644 --- a/openedx/core/djangoapps/content/search/tests/test_documents.py +++ b/openedx/core/djangoapps/content/search/tests/test_documents.py @@ -15,6 +15,8 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import BlockFactory, ToyCourseFactory +from openedx_learning.api import authoring as authoring_api + try: # This import errors in the lms because content.search is not an installed app there. from ..documents import ( @@ -528,6 +530,7 @@ def test_draft_container(self): "access_id": self.library_access_id, "breadcrumbs": [{"display_name": "some content_library"}], "created": 1680674828.0, + "publish_status": "never", "modified": 1680674828.0, # "tags" should be here but we haven't implemented them yet # "published" is not set since we haven't published it yet diff --git a/openedx/core/djangoapps/content_libraries/api/containers.py b/openedx/core/djangoapps/content_libraries/api/containers.py index c03cee2b84d8..db42321f23ed 100644 --- a/openedx/core/djangoapps/content_libraries/api/containers.py +++ b/openedx/core/djangoapps/content_libraries/api/containers.py @@ -60,6 +60,7 @@ class ContainerMetadata(PublishableItem): Class that represents the metadata about a Container (e.g. Unit) in a content library. """ container_key: LibraryContainerLocator + container_pk: int container_type: ContainerType @classmethod @@ -87,7 +88,8 @@ def from_container(cls, library_key, container: Container, associated_collection last_draft_created_by = "" return cls( - container_key=container_key, + container_key=container_key, # LibraryContainerLocator + container_pk=container.pk, # authoring_models.Container.pk container_type=container_type, display_name=draft.title, created=container.created, diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py index 9e6442b96eff..8a45fac839c3 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_api.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py @@ -778,16 +778,8 @@ def setUp(self): # TODO build API for this self.problem_block_component = api.get_component_from_usage_key(self.problem_block_usage_key) self.html_block_component = api.get_component_from_usage_key(self.html_block_usage_key) - self.unit1_container = authoring_api.get_container_by_key( - self.lib1.learning_package.id, - self.unit1.container_key.container_id, - ) - self.unit2_container = authoring_api.get_container_by_key( - self.lib1.learning_package.id, - self.unit2.container_key.container_id, - ) authoring_api.create_next_container_version( - self.unit1_container.pk, + self.unit1.container_pk, publishable_entities_pks=[ self.problem_block_component.publishable_entity.id, self.html_block_component.publishable_entity.id, @@ -798,7 +790,7 @@ def setUp(self): created_by=None, ) authoring_api.create_next_container_version( - self.unit2_container.pk, + self.unit2.container_pk, publishable_entities_pks=[self.html_block_component.publishable_entity.id], title=None, entity_version_pks=None, From 3b49af31a4a44d5758104d50c9c8bded680ae4f4 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Fri, 21 Mar 2025 20:39:11 -0500 Subject: [PATCH 03/10] feat: Add LIBRARY_CONTAINER_UPDATED whend deleted a component inside a container --- .../content_libraries/api/libraries.py | 17 +++++++++ .../content_libraries/tests/test_api.py | 36 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/openedx/core/djangoapps/content_libraries/api/libraries.py b/openedx/core/djangoapps/content_libraries/api/libraries.py index a4b001cd9a47..c17758868b1c 100644 --- a/openedx/core/djangoapps/content_libraries/api/libraries.py +++ b/openedx/core/djangoapps/content_libraries/api/libraries.py @@ -82,6 +82,7 @@ ContentLibraryData, LibraryBlockData, LibraryCollectionData, + LibraryContainerData, ContentObjectChangedData, ) from openedx_events.content_authoring.signals import ( @@ -92,6 +93,7 @@ LIBRARY_BLOCK_DELETED, LIBRARY_BLOCK_UPDATED, LIBRARY_COLLECTION_UPDATED, + LIBRARY_CONTAINER_UPDATED, CONTENT_OBJECT_ASSOCIATIONS_CHANGED, ) from openedx_learning.api import authoring as authoring_api @@ -113,6 +115,7 @@ xblock_type_display_name, ) from openedx.core.lib.xblock_serializer.api import serialize_modulestore_block_for_learning_core +from openedx.core.djangoapps.content_libraries import api as lib_api from openedx.core.types import User as UserType from xmodule.modulestore.django import modulestore @@ -1205,6 +1208,7 @@ def delete_library_block(usage_key: LibraryUsageLocatorV2, remove_from_parent=Tr component = get_component_from_usage_key(usage_key) library_key = usage_key.context_key affected_collections = authoring_api.get_entity_collections(component.learning_package_id, component.key) + affected_containers = lib_api.get_containers_contains_component(usage_key) authoring_api.soft_delete_draft(component.pk) @@ -1228,6 +1232,19 @@ def delete_library_block(usage_key: LibraryUsageLocatorV2, remove_from_parent=Tr ) ) + # For each container, trigger LIBRARY_CONTAINER_UPDATED signal and set background=True to trigger + # container indexing asynchronously. + # + # To update the components count in containers + for container in affected_containers: + LIBRARY_CONTAINER_UPDATED.send_event( + library_container=LibraryContainerData( + library_key=library_key, + container_key=container.container_pk, + background=True, + ) + ) + def restore_library_block(usage_key: LibraryUsageLocatorV2) -> None: """ diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py index 8a45fac839c3..65326c5636c5 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_api.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py @@ -17,12 +17,14 @@ from openedx_events.content_authoring.data import ( ContentObjectChangedData, LibraryCollectionData, + LibraryContainerData, ) from openedx_events.content_authoring.signals import ( CONTENT_OBJECT_ASSOCIATIONS_CHANGED, LIBRARY_COLLECTION_CREATED, LIBRARY_COLLECTION_DELETED, LIBRARY_COLLECTION_UPDATED, + LIBRARY_CONTAINER_UPDATED, ) from openedx_events.tests.utils import OpenEdxEventsTestMixin from openedx_learning.api import authoring as authoring_api @@ -808,3 +810,37 @@ def test_get_containers_contains_component(self): assert len(html_block_containers) == 2 assert html_block_containers[0].container_key == self.unit1.container_key assert html_block_containers[1].container_key == self.unit2.container_key + + + def test_call_container_update_signal_when_delete_component(self): + container_update_event_receiver = mock.Mock() + LIBRARY_CONTAINER_UPDATED.connect(container_update_event_receiver) + + api.delete_library_block(self.html_block_usage_key) + + assert container_update_event_receiver.call_count == 2 + + self.assertDictContainsSubset( + { + "signal": LIBRARY_CONTAINER_UPDATED, + "sender": None, + "library_container": LibraryContainerData( + library_key=self.lib1.library_key, + container_key=self.unit1.container_pk, + background=True, + ) + }, + container_update_event_receiver.call_args_list[0].kwargs, + ) + self.assertDictContainsSubset( + { + "signal": LIBRARY_CONTAINER_UPDATED, + "sender": None, + "library_container": LibraryContainerData( + library_key=self.lib1.library_key, + container_key=self.unit2.container_pk, + background=True, + ) + }, + container_update_event_receiver.call_args_list[1].kwargs, + ) From 1d947886f460ffd416576364946d9ec197678fcd Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Mon, 24 Mar 2025 16:46:34 -0500 Subject: [PATCH 04/10] feat: Send LIBRARY_CONTAINER_UPDATED signal when updating component of container --- .../content_libraries/api/libraries.py | 12 ++++++ .../content_libraries/library_context.py | 20 +++++++++- .../content_libraries/tests/test_api.py | 38 ++++++++++++++----- .../learning_context/learning_context.py | 8 ++++ .../xblock/runtime/learning_core_runtime.py | 1 + 5 files changed, 67 insertions(+), 12 deletions(-) diff --git a/openedx/core/djangoapps/content_libraries/api/libraries.py b/openedx/core/djangoapps/content_libraries/api/libraries.py index c17758868b1c..a4890d2597e6 100644 --- a/openedx/core/djangoapps/content_libraries/api/libraries.py +++ b/openedx/core/djangoapps/content_libraries/api/libraries.py @@ -904,6 +904,18 @@ def set_library_block_olx(usage_key: LibraryUsageLocatorV2, new_olx_str: str) -> ) ) + # For each container, trigger LIBRARY_CONTAINER_UPDATED signal and set background=True to trigger + # container indexing asynchronously. + affected_containers = lib_api.get_containers_contains_component(usage_key) + for container in affected_containers: + LIBRARY_CONTAINER_UPDATED.send_event( + library_container=LibraryContainerData( + library_key=usage_key.lib_key, + container_key=container.container_pk, + background=True, + ) + ) + return new_component_version diff --git a/openedx/core/djangoapps/content_libraries/library_context.py b/openedx/core/djangoapps/content_libraries/library_context.py index 4bda10eb12fa..15d69499ed11 100644 --- a/openedx/core/djangoapps/content_libraries/library_context.py +++ b/openedx/core/djangoapps/content_libraries/library_context.py @@ -6,8 +6,8 @@ from django.core.exceptions import PermissionDenied from rest_framework.exceptions import NotFound -from openedx_events.content_authoring.data import LibraryBlockData -from openedx_events.content_authoring.signals import LIBRARY_BLOCK_UPDATED +from openedx_events.content_authoring.data import LibraryBlockData, LibraryContainerData +from openedx_events.content_authoring.signals import LIBRARY_BLOCK_UPDATED, LIBRARY_CONTAINER_UPDATED from opaque_keys.edx.keys import UsageKeyV2 from opaque_keys.edx.locator import LibraryUsageLocatorV2, LibraryLocatorV2 from openedx_learning.api import authoring as authoring_api @@ -114,3 +114,19 @@ def send_block_updated_event(self, usage_key: UsageKeyV2): usage_key=usage_key, ) ) + + def send_container_updated_events(self, usage_key: UsageKeyV2): + """ + Send "container updated" events for containers that contains the library block + with the given usage_key. + """ + assert isinstance(usage_key, LibraryUsageLocatorV2) + affected_containers = api.get_containers_contains_component(usage_key) + for container in affected_containers: + LIBRARY_CONTAINER_UPDATED.send_event( + library_container=LibraryContainerData( + library_key=usage_key.lib_key, + container_key=container.container_pk, + background=True, + ) + ) diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py index 65326c5636c5..3d2c179aa6b0 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_api.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py @@ -812,14 +812,8 @@ def test_get_containers_contains_component(self): assert html_block_containers[1].container_key == self.unit2.container_key - def test_call_container_update_signal_when_delete_component(self): - container_update_event_receiver = mock.Mock() - LIBRARY_CONTAINER_UPDATED.connect(container_update_event_receiver) - - api.delete_library_block(self.html_block_usage_key) - - assert container_update_event_receiver.call_count == 2 - + def _validate_calls_of_html_block(self, event_mock): + assert event_mock.call_count == 2 self.assertDictContainsSubset( { "signal": LIBRARY_CONTAINER_UPDATED, @@ -830,7 +824,7 @@ def test_call_container_update_signal_when_delete_component(self): background=True, ) }, - container_update_event_receiver.call_args_list[0].kwargs, + event_mock.call_args_list[0].kwargs, ) self.assertDictContainsSubset( { @@ -842,5 +836,29 @@ def test_call_container_update_signal_when_delete_component(self): background=True, ) }, - container_update_event_receiver.call_args_list[1].kwargs, + event_mock.call_args_list[1].kwargs, ) + + def test_call_container_update_signal_when_delete_component(self): + container_update_event_receiver = mock.Mock() + LIBRARY_CONTAINER_UPDATED.connect(container_update_event_receiver) + + api.delete_library_block(self.html_block_usage_key) + self._validate_calls_of_html_block(container_update_event_receiver) + + + def test_call_container_update_signal_when_update_olx(self): + block_olx = "Hello world!" + container_update_event_receiver = mock.Mock() + LIBRARY_CONTAINER_UPDATED.connect(container_update_event_receiver) + + self._set_library_block_olx(self.html_block_usage_key, block_olx) + self._validate_calls_of_html_block(container_update_event_receiver) + + def test_call_container_update_signal_when_update_component(self): + block_olx = "Hello world!" + container_update_event_receiver = mock.Mock() + LIBRARY_CONTAINER_UPDATED.connect(container_update_event_receiver) + + self._set_library_block_fields(self.html_block_usage_key, {"data": block_olx, "metadata": {}}) + self._validate_calls_of_html_block(container_update_event_receiver) diff --git a/openedx/core/djangoapps/xblock/learning_context/learning_context.py b/openedx/core/djangoapps/xblock/learning_context/learning_context.py index b535e84ca7c1..dc7a21f1c397 100644 --- a/openedx/core/djangoapps/xblock/learning_context/learning_context.py +++ b/openedx/core/djangoapps/xblock/learning_context/learning_context.py @@ -76,3 +76,11 @@ def send_block_updated_event(self, usage_key): usage_key: the UsageKeyV2 subclass used for this learning context """ + + def send_container_updated_events(self, usage_key): + """ + Send "container updated" events for containers that contains the block with + the given usage_key in this context. + + usage_key: the UsageKeyV2 subclass used for this learning context + """ diff --git a/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py b/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py index c3885fbf11cc..57582989f60d 100644 --- a/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py +++ b/openedx/core/djangoapps/xblock/runtime/learning_core_runtime.py @@ -317,6 +317,7 @@ def save_block(self, block): # Signal that we've modified this block learning_context = get_learning_context_impl(usage_key) learning_context.send_block_updated_event(usage_key) + learning_context.send_container_updated_events(usage_key) def _get_component_from_usage_key(self, usage_key): """ From da9f51013715322be4c56ee071531ba95e41f915 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Wed, 26 Mar 2025 14:06:18 -0500 Subject: [PATCH 05/10] fix: Bugs sending LIBRARY_CONTAINER_UPDATED signal --- openedx/core/djangoapps/content_libraries/api/libraries.py | 4 ++-- openedx/core/djangoapps/content_libraries/library_context.py | 2 +- openedx/core/djangoapps/content_libraries/tests/test_api.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/openedx/core/djangoapps/content_libraries/api/libraries.py b/openedx/core/djangoapps/content_libraries/api/libraries.py index a4890d2597e6..3884614ae445 100644 --- a/openedx/core/djangoapps/content_libraries/api/libraries.py +++ b/openedx/core/djangoapps/content_libraries/api/libraries.py @@ -911,7 +911,7 @@ def set_library_block_olx(usage_key: LibraryUsageLocatorV2, new_olx_str: str) -> LIBRARY_CONTAINER_UPDATED.send_event( library_container=LibraryContainerData( library_key=usage_key.lib_key, - container_key=container.container_pk, + container_key=str(container.container_key), background=True, ) ) @@ -1252,7 +1252,7 @@ def delete_library_block(usage_key: LibraryUsageLocatorV2, remove_from_parent=Tr LIBRARY_CONTAINER_UPDATED.send_event( library_container=LibraryContainerData( library_key=library_key, - container_key=container.container_pk, + container_key=str(container.container_key), background=True, ) ) diff --git a/openedx/core/djangoapps/content_libraries/library_context.py b/openedx/core/djangoapps/content_libraries/library_context.py index 15d69499ed11..d5f121d8396e 100644 --- a/openedx/core/djangoapps/content_libraries/library_context.py +++ b/openedx/core/djangoapps/content_libraries/library_context.py @@ -126,7 +126,7 @@ def send_container_updated_events(self, usage_key: UsageKeyV2): LIBRARY_CONTAINER_UPDATED.send_event( library_container=LibraryContainerData( library_key=usage_key.lib_key, - container_key=container.container_pk, + container_key=str(container.container_key), background=True, ) ) diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py index 3d2c179aa6b0..e59e9d26eb24 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_api.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py @@ -820,7 +820,7 @@ def _validate_calls_of_html_block(self, event_mock): "sender": None, "library_container": LibraryContainerData( library_key=self.lib1.library_key, - container_key=self.unit1.container_pk, + container_key=str(self.unit1.container_key), background=True, ) }, @@ -832,7 +832,7 @@ def _validate_calls_of_html_block(self, event_mock): "sender": None, "library_container": LibraryContainerData( library_key=self.lib1.library_key, - container_key=self.unit2.container_pk, + container_key=str(self.unit2.container_key), background=True, ) }, From 6c1270994fc725b8f83a286dc582e181d740d631 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Wed, 26 Mar 2025 14:14:03 -0500 Subject: [PATCH 06/10] feat: Add publish_status of container as PublishStatus.Never by default --- openedx/core/djangoapps/content/search/documents.py | 1 + 1 file changed, 1 insertion(+) diff --git a/openedx/core/djangoapps/content/search/documents.py b/openedx/core/djangoapps/content/search/documents.py index c6ca52098abc..061015751955 100644 --- a/openedx/core/djangoapps/content/search/documents.py +++ b/openedx/core/djangoapps/content/search/documents.py @@ -572,6 +572,7 @@ def searchable_doc_for_container( Fields.usage_key: str(container_key), # Field name isn't exact but this is the closest match Fields.block_id: container_key.container_id, # Field name isn't exact but this is the closest match Fields.access_id: _meili_access_id_from_context_key(container_key.library_key), + Fields.publish_status: PublishStatus.never, } try: From a5bcc11c56a1963dcf9791a3f741eee9ba90d288 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 1 Apr 2025 18:26:01 -0500 Subject: [PATCH 07/10] refactor: ContentLibraryContainersTest to use update_container_children to add components --- .../content_libraries/api/containers.py | 2 - .../content_libraries/tests/test_api.py | 39 +++++++------------ 2 files changed, 13 insertions(+), 28 deletions(-) diff --git a/openedx/core/djangoapps/content_libraries/api/containers.py b/openedx/core/djangoapps/content_libraries/api/containers.py index db42321f23ed..f0513bf4c68c 100644 --- a/openedx/core/djangoapps/content_libraries/api/containers.py +++ b/openedx/core/djangoapps/content_libraries/api/containers.py @@ -60,7 +60,6 @@ class ContainerMetadata(PublishableItem): Class that represents the metadata about a Container (e.g. Unit) in a content library. """ container_key: LibraryContainerLocator - container_pk: int container_type: ContainerType @classmethod @@ -89,7 +88,6 @@ def from_container(cls, library_key, container: Container, associated_collection return cls( container_key=container_key, # LibraryContainerLocator - container_pk=container.pk, # authoring_models.Container.pk container_type=container_type, display_name=draft.title, created=container.created, diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py index e59e9d26eb24..7ea797dfbb8d 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_api.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py @@ -766,38 +766,25 @@ def setUp(self): # Create XBlocks # Create some library blocks in lib1 - self.problem_block_dict = self._add_block_to_library( + self.problem_block = self._add_block_to_library( self.lib1.library_key, "problem", "problem1", ) - self.problem_block_usage_key = UsageKey.from_string(self.problem_block_dict["id"]) - self.html_block_dict = self._add_block_to_library( + self.problem_block_usage_key = UsageKey.from_string(self.problem_block["id"]) + self.html_block = self._add_block_to_library( self.lib1.library_key, "html", "html1", ) - self.html_block_usage_key = UsageKey.from_string(self.html_block_dict["id"]) - now = datetime.now(tz=timezone.utc) + self.html_block_usage_key = UsageKey.from_string(self.html_block["id"]) # Add content to units - # TODO build API for this - self.problem_block_component = api.get_component_from_usage_key(self.problem_block_usage_key) - self.html_block_component = api.get_component_from_usage_key(self.html_block_usage_key) - authoring_api.create_next_container_version( - self.unit1.container_pk, - publishable_entities_pks=[ - self.problem_block_component.publishable_entity.id, - self.html_block_component.publishable_entity.id, - ], - title=None, - entity_version_pks=None, - created=now, - created_by=None, - ) - authoring_api.create_next_container_version( - self.unit2.container_pk, - publishable_entities_pks=[self.html_block_component.publishable_entity.id], - title=None, - entity_version_pks=None, - created=now, - created_by=None, + api.update_container_children( + self.unit1.container_key, + [self.problem_block_usage_key, self.html_block_usage_key], + None, + ) + api.update_container_children( + self.unit2.container_key, + [self.html_block_usage_key], + None, ) def test_get_containers_contains_component(self): From 74d11a0a35b0f6a05224b3b44ecdcc3d8c6c7854 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 1 Apr 2025 18:32:49 -0500 Subject: [PATCH 08/10] style: Clean code after fix conflicts --- openedx/core/djangoapps/content/search/tests/test_documents.py | 3 --- openedx/core/djangoapps/content_libraries/api/containers.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/openedx/core/djangoapps/content/search/tests/test_documents.py b/openedx/core/djangoapps/content/search/tests/test_documents.py index ee2253347f20..a2964436d039 100644 --- a/openedx/core/djangoapps/content/search/tests/test_documents.py +++ b/openedx/core/djangoapps/content/search/tests/test_documents.py @@ -15,8 +15,6 @@ from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import BlockFactory, ToyCourseFactory -from openedx_learning.api import authoring as authoring_api - try: # This import errors in the lms because content.search is not an installed app there. from ..documents import ( @@ -530,7 +528,6 @@ def test_draft_container(self): "access_id": self.library_access_id, "breadcrumbs": [{"display_name": "some content_library"}], "created": 1680674828.0, - "publish_status": "never", "modified": 1680674828.0, # "tags" should be here but we haven't implemented them yet # "published" is not set since we haven't published it yet diff --git a/openedx/core/djangoapps/content_libraries/api/containers.py b/openedx/core/djangoapps/content_libraries/api/containers.py index f0513bf4c68c..c03cee2b84d8 100644 --- a/openedx/core/djangoapps/content_libraries/api/containers.py +++ b/openedx/core/djangoapps/content_libraries/api/containers.py @@ -87,7 +87,7 @@ def from_container(cls, library_key, container: Container, associated_collection last_draft_created_by = "" return cls( - container_key=container_key, # LibraryContainerLocator + container_key=container_key, container_type=container_type, display_name=draft.title, created=container.created, From 7176b20c8a4677a4372648a2f7df744317f6ccc1 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 1 Apr 2025 18:41:53 -0500 Subject: [PATCH 09/10] fix: Broken lint --- openedx/core/djangoapps/content_libraries/tests/test_api.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py index 7ea797dfbb8d..48a453f411e5 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_api.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py @@ -5,7 +5,6 @@ import base64 import hashlib from unittest import mock -from datetime import datetime, timezone from django.test import TestCase @@ -800,6 +799,10 @@ def test_get_containers_contains_component(self): def _validate_calls_of_html_block(self, event_mock): + """ + Validate that the `event_mock` has been called twice + using the `LIBRARY_CONTAINER_UPDATED` signal. + """ assert event_mock.call_count == 2 self.assertDictContainsSubset( { @@ -832,7 +835,6 @@ def test_call_container_update_signal_when_delete_component(self): api.delete_library_block(self.html_block_usage_key) self._validate_calls_of_html_block(container_update_event_receiver) - def test_call_container_update_signal_when_update_olx(self): block_olx = "Hello world!" From 9f7a1211a5cf9acff71f1c6ed544e2a1ddaad2f3 Mon Sep 17 00:00:00 2001 From: XnpioChV Date: Tue, 1 Apr 2025 18:50:39 -0500 Subject: [PATCH 10/10] fix: lint --- openedx/core/djangoapps/content_libraries/tests/test_api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openedx/core/djangoapps/content_libraries/tests/test_api.py b/openedx/core/djangoapps/content_libraries/tests/test_api.py index 48a453f411e5..a1475aa1a039 100644 --- a/openedx/core/djangoapps/content_libraries/tests/test_api.py +++ b/openedx/core/djangoapps/content_libraries/tests/test_api.py @@ -797,7 +797,6 @@ def test_get_containers_contains_component(self): assert html_block_containers[0].container_key == self.unit1.container_key assert html_block_containers[1].container_key == self.unit2.container_key - def _validate_calls_of_html_block(self, event_mock): """ Validate that the `event_mock` has been called twice