-
Notifications
You must be signed in to change notification settings - Fork 4.2k
feat: Basic CRUD support for sections/subsections as containers [FC-0090] #36762
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
8b9731d
3f6c616
c9300cf
d921f53
e08f1b1
7c478d3
8ed07f3
b269d46
539f26c
c1a0c08
cbd5c84
02e70f0
b55ccc0
edd601f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -48,6 +48,7 @@ class TestSearchApi(ModuleStoreTestCase): | |
| MODULESTORE = TEST_DATA_SPLIT_MODULESTORE | ||
|
|
||
| def setUp(self): | ||
| # pylint: disable=too-many-statements | ||
| super().setUp() | ||
| self.user = UserFactory.create() | ||
| self.user_id = self.user.id | ||
|
|
@@ -219,7 +220,7 @@ def setUp(self): | |
| "breadcrumbs": [{"display_name": "Library"}], | ||
| } | ||
|
|
||
| # Create a unit: | ||
| # Create a container: | ||
| with freeze_time(self.created_date): | ||
| self.unit = library_api.create_container( | ||
| library_key=self.library.key, | ||
|
|
@@ -229,6 +230,23 @@ def setUp(self): | |
| user_id=None, | ||
| ) | ||
| self.unit_key = "lct:org1:lib:unit:unit-1" | ||
| self.subsection = library_api.create_container( | ||
| self.library.key, | ||
| container_type=library_api.ContainerType.Subsection, | ||
| slug="subsection-1", | ||
| title="Subsection 1", | ||
| user_id=None, | ||
| ) | ||
| self.subsection_key = "lct:org1:lib:subsection:subsection-1" | ||
| self.section = library_api.create_container( | ||
| self.library.key, | ||
| container_type=library_api.ContainerType.Section, | ||
| slug="section-1", | ||
| title="Section 1", | ||
| user_id=None, | ||
| ) | ||
| self.section_key = "lct:org1:lib:section:section-1" | ||
|
|
||
| self.unit_dict = { | ||
| "id": "lctorg1libunitunit-1-e4527f7c", | ||
| "block_id": "unit-1", | ||
|
|
@@ -249,6 +267,46 @@ def setUp(self): | |
| "breadcrumbs": [{"display_name": "Library"}], | ||
| # "published" is not set since we haven't published it yet | ||
| } | ||
| self.subsection_dict = { | ||
| "id": "lctorg1libsubsectionsubsection-1-cf808309", | ||
| "block_id": "subsection-1", | ||
| "block_type": "subsection", | ||
| "usage_key": self.subsection_key, | ||
| "type": "library_container", | ||
| "display_name": "Subsection 1", | ||
| # description is not set for containers | ||
| "num_children": 0, | ||
| "content": {"child_usage_keys": []}, | ||
| "publish_status": "never", | ||
| "context_key": "lib:org1:lib", | ||
| "org": "org1", | ||
| "created": self.created_date.timestamp(), | ||
| "modified": self.created_date.timestamp(), | ||
| "last_published": None, | ||
| "access_id": lib_access.id, | ||
| "breadcrumbs": [{"display_name": "Library"}], | ||
| # "published" is not set since we haven't published it yet | ||
| } | ||
| self.section_dict = { | ||
| "id": "lctorg1libsectionsection-1-dc4791a4", | ||
| "block_id": "section-1", | ||
| "block_type": "section", | ||
| "usage_key": self.section_key, | ||
| "type": "library_container", | ||
| "display_name": "Section 1", | ||
| # description is not set for containers | ||
| "num_children": 0, | ||
| "content": {"child_usage_keys": []}, | ||
| "publish_status": "never", | ||
| "context_key": "lib:org1:lib", | ||
| "org": "org1", | ||
| "created": self.created_date.timestamp(), | ||
| "modified": self.created_date.timestamp(), | ||
| "last_published": None, | ||
| "access_id": lib_access.id, | ||
| "breadcrumbs": [{"display_name": "Library"}], | ||
| # "published" is not set since we haven't published it yet | ||
| } | ||
|
|
||
| @override_settings(MEILISEARCH_ENABLED=False) | ||
| def test_reindex_meilisearch_disabled(self, mock_meilisearch): | ||
|
|
@@ -278,6 +336,12 @@ def test_reindex_meilisearch(self, mock_meilisearch): | |
| doc_unit = copy.deepcopy(self.unit_dict) | ||
| doc_unit["tags"] = {} | ||
| doc_unit["collections"] = {'display_name': [], 'key': []} | ||
| doc_subsection = copy.deepcopy(self.subsection_dict) | ||
| doc_subsection["tags"] = {} | ||
| doc_subsection["collections"] = {'display_name': [], 'key': []} | ||
| doc_section = copy.deepcopy(self.section_dict) | ||
| doc_section["tags"] = {} | ||
| doc_section["collections"] = {'display_name': [], 'key': []} | ||
|
|
||
| api.rebuild_index() | ||
| assert mock_meilisearch.return_value.index.return_value.add_documents.call_count == 4 | ||
|
|
@@ -286,7 +350,7 @@ def test_reindex_meilisearch(self, mock_meilisearch): | |
| call([doc_sequential, doc_vertical]), | ||
| call([doc_problem1, doc_problem2]), | ||
| call([doc_collection]), | ||
| call([doc_unit]), | ||
| call([doc_unit, doc_subsection, doc_section]), | ||
| ], | ||
| any_order=True, | ||
| ) | ||
|
|
@@ -312,6 +376,12 @@ def test_reindex_meilisearch_incremental(self, mock_meilisearch): | |
| doc_unit = copy.deepcopy(self.unit_dict) | ||
| doc_unit["tags"] = {} | ||
| doc_unit["collections"] = {"display_name": [], "key": []} | ||
| doc_subsection = copy.deepcopy(self.subsection_dict) | ||
| doc_subsection["tags"] = {} | ||
| doc_subsection["collections"] = {'display_name': [], 'key': []} | ||
| doc_section = copy.deepcopy(self.section_dict) | ||
| doc_section["tags"] = {} | ||
| doc_section["collections"] = {'display_name': [], 'key': []} | ||
|
|
||
| api.rebuild_index(incremental=True) | ||
| assert mock_meilisearch.return_value.index.return_value.add_documents.call_count == 4 | ||
|
|
@@ -320,7 +390,7 @@ def test_reindex_meilisearch_incremental(self, mock_meilisearch): | |
| call([doc_sequential, doc_vertical]), | ||
| call([doc_problem1, doc_problem2]), | ||
| call([doc_collection]), | ||
| call([doc_unit]), | ||
| call([doc_unit, doc_subsection, doc_section]), | ||
| ], | ||
| any_order=True, | ||
| ) | ||
|
|
@@ -894,15 +964,23 @@ def test_delete_collection(self, mock_meilisearch): | |
| any_order=True, | ||
| ) | ||
|
|
||
| @ddt.data( | ||
| "unit", | ||
| "subsection", | ||
| "section", | ||
| ) | ||
| @override_settings(MEILISEARCH_ENABLED=True) | ||
| def test_delete_index_container(self, mock_meilisearch): | ||
| def test_delete_index_container(self, container_type, mock_meilisearch): | ||
| """ | ||
| Test delete a container index. | ||
| """ | ||
| library_api.delete_container(self.unit.container_key) | ||
| container = getattr(self, container_type) | ||
| container_dict = getattr(self, f"{container_type}_dict") | ||
|
|
||
| library_api.delete_container(container.container_key) | ||
|
|
||
| mock_meilisearch.return_value.index.return_value.delete_document.assert_called_once_with( | ||
| self.unit_dict["id"], | ||
| container_dict["id"], | ||
| ) | ||
|
|
||
| @override_settings(MEILISEARCH_ENABLED=True) | ||
|
|
@@ -914,22 +992,30 @@ def test_index_library_container_metadata(self, mock_meilisearch): | |
|
|
||
| mock_meilisearch.return_value.index.return_value.update_documents.assert_called_once_with([self.unit_dict]) | ||
|
|
||
| @ddt.data( | ||
| ("unit", "lctorg1libunitunit-1-e4527f7c"), | ||
| ("subsection", "lctorg1libsubsectionsubsection-1-cf808309"), | ||
| ("section", "lctorg1libsectionsection-1-dc4791a4"), | ||
| ) | ||
| @ddt.unpack | ||
| @override_settings(MEILISEARCH_ENABLED=True) | ||
| def test_index_tags_in_containers(self, mock_meilisearch): | ||
| # Tag collection | ||
| tagging_api.tag_object(self.unit_key, self.taxonomyA, ["one", "two"]) | ||
| tagging_api.tag_object(self.unit_key, self.taxonomyB, ["three", "four"]) | ||
| def test_index_tags_in_containers(self, container_type, container_id, mock_meilisearch): | ||
| container_key = getattr(self, f"{container_type}_key") | ||
|
|
||
| # Tag container | ||
| tagging_api.tag_object(container_key, self.taxonomyA, ["one", "two"]) | ||
| tagging_api.tag_object(container_key, self.taxonomyB, ["three", "four"]) | ||
|
|
||
| # Build expected docs with tags at each stage | ||
| doc_unit_with_tags1 = { | ||
| "id": "lctorg1libunitunit-1-e4527f7c", | ||
| "id": container_id, | ||
| "tags": { | ||
| 'taxonomy': ['A'], | ||
| 'level0': ['A > one', 'A > two'] | ||
| } | ||
| } | ||
| doc_unit_with_tags2 = { | ||
| "id": "lctorg1libunitunit-1-e4527f7c", | ||
| "id": container_id, | ||
| "tags": { | ||
| 'taxonomy': ['A', 'B'], | ||
| 'level0': ['A > one', 'A > two', 'B > four', 'B > three'] | ||
|
|
@@ -975,3 +1061,51 @@ def test_block_in_units(self, mock_meilisearch): | |
| ], | ||
| any_order=True, | ||
| ) | ||
|
|
||
| @override_settings(MEILISEARCH_ENABLED=True) | ||
| def test_units_in_subsection(self, mock_meilisearch): | ||
bradenmacdonald marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| with freeze_time(self.created_date): | ||
| library_api.update_container_children( | ||
| LibraryContainerLocator.from_string(self.subsection_key), | ||
| [LibraryContainerLocator.from_string(self.unit_key)], | ||
| None, | ||
| ) | ||
|
|
||
| # TODO verify subsections in units | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's left to do here? This looks similar to the units case above.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was missing to add to the index the sections and subsections to which it is contained. Navin has advanced this part in #36762 (comment). I'll review it and update the tests. |
||
|
|
||
| new_subsection_dict = { | ||
| **self.subsection_dict, | ||
| "num_children": 1, | ||
| 'content': {'child_usage_keys': [self.unit_key]} | ||
| } | ||
| assert mock_meilisearch.return_value.index.return_value.update_documents.call_count == 1 | ||
| mock_meilisearch.return_value.index.return_value.update_documents.assert_has_calls( | ||
| [ | ||
| call([new_subsection_dict]), | ||
| ], | ||
| any_order=True, | ||
| ) | ||
|
|
||
| @override_settings(MEILISEARCH_ENABLED=True) | ||
| def test_section_in_usbsections(self, mock_meilisearch): | ||
| with freeze_time(self.created_date): | ||
| library_api.update_container_children( | ||
| LibraryContainerLocator.from_string(self.section_key), | ||
| [LibraryContainerLocator.from_string(self.subsection_key)], | ||
| None, | ||
| ) | ||
|
|
||
| # TODO verify section in subsections | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same question.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same of #36762 (comment) |
||
|
|
||
| new_section_dict = { | ||
| **self.section_dict, | ||
| "num_children": 1, | ||
| 'content': {'child_usage_keys': [self.subsection_key]} | ||
| } | ||
| assert mock_meilisearch.return_value.index.return_value.update_documents.call_count == 1 | ||
| mock_meilisearch.return_value.index.return_value.update_documents.assert_has_calls( | ||
| [ | ||
| call([new_section_dict]), | ||
| ], | ||
| any_order=True, | ||
| ) | ||
Uh oh!
There was an error while loading. Please reload this page.