diff --git a/cms/djangoapps/import_from_modulestore/README.rst b/cms/djangoapps/import_from_modulestore/README.rst
deleted file mode 100644
index f2725ef4226d..000000000000
--- a/cms/djangoapps/import_from_modulestore/README.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-========================
-Import from Modulestore
-========================
-
-The new Django application `import_from_modulestore` is designed to
-automate the process of importing course legacy OLX content from Modulestore
-to Content Libraries. The application allows users to easily and quickly
-migrate existing course content, minimizing the manual work and potential
-errors associated with manual migration.
-The new app makes the import process automated and easy to manage.
-
-The main problems solved by the application:
-
-* Reducing the time to import course content.
-* Ensuring data integrity during the transfer.
-* Ability to choose which content to import before the final import.
-
-------------------------------
-Import from Modulestore Usage
-------------------------------
-
-* Import course elements at the level of sections, subsections, units,
- and xblocks into the Content Libraries.
-* Choose the structure of this import, whether it will be only xblocks
- from a particular course or full sections/subsections/units.
-* Store the history of imports.
-* Synchronize the course content with the library content (when re-importing,
- the blocks can be updated according to changes in the original course).
-* The new import mechanism ensures data integrity at the time of importing
- by saving the course in StagedContent.
-* Importing the legacy library content into the new Content Libraries.
diff --git a/cms/djangoapps/import_from_modulestore/admin.py b/cms/djangoapps/import_from_modulestore/admin.py
deleted file mode 100644
index ed1d7a202303..000000000000
--- a/cms/djangoapps/import_from_modulestore/admin.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""
-This module contains the admin configuration for the Import model.
-"""
-from django.contrib import admin
-
-from .models import Import, PublishableEntityImport, PublishableEntityMapping
-
-
-class ImportAdmin(admin.ModelAdmin):
- """
- Admin configuration for the Import model.
- """
-
- list_display = (
- 'uuid',
- 'created',
- 'status',
- 'source_key',
- 'target_change',
- )
- list_filter = (
- 'status',
- )
- search_fields = (
- 'source_key',
- 'target_change',
- )
-
- raw_id_fields = ('user',)
- readonly_fields = ('status',)
-
-
-admin.site.register(Import, ImportAdmin)
-admin.site.register(PublishableEntityImport)
-admin.site.register(PublishableEntityMapping)
diff --git a/cms/djangoapps/import_from_modulestore/api.py b/cms/djangoapps/import_from_modulestore/api.py
deleted file mode 100644
index 7f8dc16b76cb..000000000000
--- a/cms/djangoapps/import_from_modulestore/api.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"""
-API for course to library import.
-"""
-from typing import Sequence
-
-from opaque_keys.edx.keys import LearningContextKey, UsageKey
-
-from .helpers import cancel_incomplete_old_imports
-from .models import Import as _Import
-from .tasks import import_staged_content_to_library_task, save_legacy_content_to_staged_content_task
-from .validators import validate_usage_keys_to_import
-
-
-def stage_content_for_import(source_key: LearningContextKey, user_id: int) -> _Import:
- """
- Create a new import event to import a course to a library and save course to staged content.
- """
- import_from_modulestore = _Import.objects.create(source_key=source_key, user_id=user_id)
- cancel_incomplete_old_imports(import_from_modulestore)
- save_legacy_content_to_staged_content_task.delay_on_commit(import_from_modulestore.uuid)
- return import_from_modulestore
-
-
-def import_staged_content_to_library(
- usage_ids: Sequence[str | UsageKey],
- import_uuid: str,
- target_learning_package_id: int,
- user_id: int,
- composition_level: str,
- override: bool,
-) -> None:
- """
- Import staged content to a library from staged content.
- """
- validate_usage_keys_to_import(usage_ids)
- import_staged_content_to_library_task.apply_async(
- kwargs={
- 'usage_key_strings': usage_ids,
- 'import_uuid': import_uuid,
- 'learning_package_id': target_learning_package_id,
- 'user_id': user_id,
- 'composition_level': composition_level,
- 'override': override,
- },
- )
diff --git a/cms/djangoapps/import_from_modulestore/constants.py b/cms/djangoapps/import_from_modulestore/constants.py
deleted file mode 100644
index 09e0d4e30f1a..000000000000
--- a/cms/djangoapps/import_from_modulestore/constants.py
+++ /dev/null
@@ -1,5 +0,0 @@
-"""
-Constants for import_from_modulestore app
-"""
-
-IMPORT_FROM_MODULESTORE_STAGING_PURPOSE = "import_from_modulestore"
diff --git a/cms/djangoapps/import_from_modulestore/helpers.py b/cms/djangoapps/import_from_modulestore/helpers.py
deleted file mode 100644
index e540e0ff3dba..000000000000
--- a/cms/djangoapps/import_from_modulestore/helpers.py
+++ /dev/null
@@ -1,466 +0,0 @@
-"""
-Helper functions for importing course content into a library.
-"""
-from datetime import datetime, timezone
-from functools import partial
-import logging
-import mimetypes
-import os
-import secrets
-from typing import TYPE_CHECKING
-
-from django.db import transaction
-from django.db.utils import IntegrityError
-from lxml import etree
-
-from opaque_keys.edx.keys import UsageKey
-from opaque_keys.edx.locator import CourseLocator
-from openedx_learning.api import authoring as authoring_api
-from openedx_learning.api.authoring_models import Component, Container, ContainerVersion, PublishableEntity
-
-from openedx.core.djangoapps.content_libraries import api
-from openedx.core.djangoapps.content_staging import api as content_staging_api
-from xmodule.modulestore.django import modulestore
-
-from .data import CompositionLevel, ImportStatus, PublishableVersionWithMapping
-from .models import Import, PublishableEntityMapping
-
-if TYPE_CHECKING:
- from openedx_learning.apps.authoring_models import LearningPackage
- from xblock.core import XBlock
-
- from openedx.core.djangoapps.content_staging.api import _StagedContent as StagedContent
-
-
-log = logging.getLogger(__name__)
-parser = etree.XMLParser(strip_cdata=False)
-
-
-class ImportClient:
- """
- Client for importing course content into a library.
-
- This class handles the import of course content from staged content into a
- content library, creating the appropriate container hierarchy based on the
- specified composition level.
- """
-
- # The create functions have different kwarg names for the child list,
- # so we need to use partial to set the child list to empty.
- CONTAINER_CREATORS_MAP: dict[str, partial] = {
- api.ContainerType.Section.olx_tag: partial(authoring_api.create_section_and_version, subsections=[]),
- api.ContainerType.Subsection.olx_tag: partial(authoring_api.create_subsection_and_version, units=[]),
- api.ContainerType.Unit.olx_tag: partial(authoring_api.create_unit_and_version, components=[]),
- }
-
- CONTAINER_OVERRIDERS_MAP: dict[str, partial] = {
- api.ContainerType.Section.olx_tag: partial(authoring_api.create_next_section_version, subsections=[]),
- api.ContainerType.Subsection.olx_tag: partial(authoring_api.create_next_subsection_version, units=[]),
- api.ContainerType.Unit.olx_tag: partial(authoring_api.create_next_unit_version, components=[]),
- }
-
- def __init__(
- self,
- import_event: Import,
- block_usage_key_to_import: str,
- target_learning_package: 'LearningPackage',
- staged_content: 'StagedContent',
- composition_level: str,
- override: bool = False,
- ):
- self.import_event = import_event
- self.block_usage_key_to_import = block_usage_key_to_import
- self.learning_package = target_learning_package
- self.staged_content = staged_content
- self.composition_level = composition_level
- self.override = override
-
- self.user_id = import_event.user_id
- self.content_library = target_learning_package.contentlibrary
- self.library_key = self.content_library.library_key
- self.parser = etree.XMLParser(strip_cdata=False)
-
- def import_from_staged_content(self) -> list[PublishableVersionWithMapping]:
- """
- Import staged content into a library.
- """
- node = etree.fromstring(self.staged_content.olx, parser=parser)
- usage_key = UsageKey.from_string(self.block_usage_key_to_import)
- block_to_import = get_node_for_usage_key(node, usage_key)
- if block_to_import is None:
- return []
-
- return self._process_import(self.block_usage_key_to_import, block_to_import)
-
- def _process_import(self, usage_key_string, block_to_import) -> list[PublishableVersionWithMapping]:
- """
- Process import of a block from staged content into a library.
-
- Imports a block and its children into the library based on the
- composition level. It handles both simple and complicated blocks, creating
- the necessary container hierarchy.
- """
- usage_key = UsageKey.from_string(usage_key_string)
- result = []
-
- if block_to_import.tag not in CompositionLevel.OLX_COMPLEX_LEVELS.value:
- return self._import_simple_block(block_to_import, usage_key)
-
- for child in block_to_import.getchildren():
- child_usage_key_string = get_usage_key_string_from_staged_content(
- self.staged_content, child.get('url_name')
- )
- if not child_usage_key_string:
- continue
-
- result.extend(self._import_child_block(child, child_usage_key_string))
-
- if self.composition_level == CompositionLevel.COMPONENT.value:
- return [
- publishable_version_with_mapping for publishable_version_with_mapping in result
- if not isinstance(publishable_version_with_mapping.publishable_version, ContainerVersion)
- ]
- return result
-
- def _import_simple_block(self, block_to_import, usage_key) -> list[PublishableVersionWithMapping]:
- """
- Import a simple block into the library.
-
- Creates a block in the library from the staged content block.
- It returns a list containing the created component version.
- """
- publishable_version_with_mapping = self._create_block_in_library(block_to_import, usage_key)
- return [publishable_version_with_mapping] if publishable_version_with_mapping else []
-
- def _import_child_block(self, child, child_usage_key_string):
- """
- Import a child block into the library.
-
- Determines whether the child block is simple or complicated and
- delegates the import process to the appropriate helper method.
- """
- child_usage_key = UsageKey.from_string(child_usage_key_string)
- if child.tag in CompositionLevel.OLX_COMPLEX_LEVELS.value:
- return self._import_complicated_child(child, child_usage_key_string)
- else:
- return self._import_simple_block(child, child_usage_key)
-
- def _import_complicated_child(self, child, child_usage_key_string):
- """
- Import a complicated child block into the library.
-
- Handles the import of complicated child blocks, including creating
- containers and updating components.
- Returns a list containing the created container version.
- """
- if not self._should_create_container(child.tag):
- return self._process_import(child_usage_key_string, child)
-
- container_version_with_mapping = self.get_or_create_container(
- child.tag,
- child.get('url_name'),
- child.get('display_name', child.tag),
- child_usage_key_string,
- )
- child_component_versions_with_mapping = self._process_import(child_usage_key_string, child)
- child_component_versions = [
- child_component_version.publishable_version for child_component_version
- in child_component_versions_with_mapping
- ]
- self._update_container_components(container_version_with_mapping.publishable_version, child_component_versions)
- return [container_version_with_mapping] + child_component_versions_with_mapping
-
- def _should_create_container(self, container_type: str) -> bool:
- """
- Determine if a new container should be created.
-
- Container type should be at a lower level than the current composition level.
- """
- composition_hierarchy = CompositionLevel.OLX_COMPLEX_LEVELS.value
- return (
- container_type in composition_hierarchy and
- self.composition_level in composition_hierarchy and
- composition_hierarchy.index(container_type) <= composition_hierarchy.index(self.composition_level)
- )
-
- def get_or_create_container(
- self,
- container_type: str,
- key: str,
- display_name: str,
- block_usage_key_string: str
- ) -> PublishableVersionWithMapping:
- """
- Create a container of the specified type.
-
- Creates a container (e.g., chapter, sequential, vertical) in the
- content library.
- """
- try:
- container_creator_func = self.CONTAINER_CREATORS_MAP[container_type]
- container_override_func = self.CONTAINER_OVERRIDERS_MAP[container_type]
- except KeyError as exc:
- raise ValueError(f"Unknown container type: {container_type}") from exc
-
- try:
- container_version = self.content_library.learning_package.publishable_entities.get(key=key)
- except PublishableEntity.DoesNotExist:
- container_version = None
-
- if container_version and self.override:
- container_version = container_override_func(
- container_version.container,
- title=display_name or f"New {container_type}",
- created=datetime.now(tz=timezone.utc),
- created_by=self.import_event.user_id,
- )
- elif not container_version:
- _, container_version = container_creator_func(
- self.learning_package.id,
- key=key or secrets.token_hex(16),
- title=display_name or f"New {container_type}",
- created=datetime.now(tz=timezone.utc),
- created_by=self.import_event.user_id,
- )
-
- publishable_entity_mapping, _ = get_or_create_publishable_entity_mapping(
- block_usage_key_string,
- container_version.container
- )
-
- return PublishableVersionWithMapping(container_version, publishable_entity_mapping)
-
- def _update_container_components(self, container_version, component_versions):
- """
- Update components of a container.
- """
- entity_rows = [
- authoring_api.ContainerEntityRow(
- entity_pk=cv.container.pk if isinstance(cv, ContainerVersion) else cv.component.pk,
- version_pk=cv.pk,
- )
- for cv in component_versions
- ]
- return authoring_api.create_next_container_version(
- container_pk=container_version.container.pk,
- title=container_version.title,
- entity_rows=entity_rows,
- created=datetime.now(tz=timezone.utc),
- created_by=self.import_event.user_id,
- container_version_cls=container_version.__class__,
- )
-
- def _create_block_in_library(self, block_to_import, usage_key) -> PublishableVersionWithMapping | None:
- """
- Create a block in a library from a staged content block.
- """
- now = datetime.now(tz=timezone.utc)
- staged_content_files = content_staging_api.get_staged_content_static_files(self.staged_content.id)
-
- with transaction.atomic():
- component_type = authoring_api.get_or_create_component_type("xblock.v1", usage_key.block_type)
- does_component_exist = authoring_api.get_components(
- self.learning_package.id
- ).filter(local_key=usage_key.block_id).exists()
-
- if does_component_exist:
- if not self.override:
- log.info(f"Component {usage_key.block_id} already exists in library {self.library_key}, skipping.")
- return None
- else:
- component_version = self._handle_component_override(usage_key, etree.tostring(block_to_import))
- else:
- try:
- _, library_usage_key = api.validate_can_add_block_to_library(
- self.library_key,
- block_to_import.tag,
- usage_key.block_id,
- )
- except api.IncompatibleTypesError as e:
- log.error(f"Error validating block {usage_key} for library {self.library_key}: {e}")
- return None
-
- authoring_api.create_component(
- self.learning_package.id,
- component_type=component_type,
- local_key=usage_key.block_id,
- created=now,
- created_by=self.import_event.user_id,
- )
- component_version = api.set_library_block_olx(library_usage_key, etree.tostring(block_to_import))
-
- self._process_staged_content_files(
- component_version,
- staged_content_files,
- usage_key,
- block_to_import,
- now,
- )
- publishable_entity_mapping, _ = get_or_create_publishable_entity_mapping(
- usage_key,
- component_version.component
- )
- return PublishableVersionWithMapping(component_version, publishable_entity_mapping)
-
- def _handle_component_override(self, usage_key, new_content):
- """
- Create new ComponentVersion for overridden component.
- """
- component_version = None
- try:
- component = authoring_api.get_components(self.learning_package.id).get(local_key=usage_key.block_id)
- except Component.DoesNotExist:
- return component_version
- library_usage_key = api.library_component_usage_key(self.library_key, component)
-
- component_version = api.set_library_block_olx(library_usage_key, new_content)
-
- return component_version
-
- def _process_staged_content_files(
- self,
- component_version,
- staged_content_files,
- usage_key,
- block_to_import,
- created_at,
- ):
- """
- Process staged content files for a component.
-
- Processes the staged content files for a component, creating the
- necessary file content and associating it with the component version.
- """
- block_olx = etree.tostring(block_to_import).decode('utf-8')
-
- for staged_content_file_data in staged_content_files:
- original_filename = staged_content_file_data.filename
- file_basename = os.path.basename(original_filename)
- file_basename_no_ext, _ = os.path.splitext(file_basename)
-
- # Skip files not referenced in the block
- if file_basename not in block_olx and file_basename_no_ext not in block_olx:
- log.info(f"Skipping file {original_filename} as it is not referenced in block {usage_key}")
- continue
-
- file_data = content_staging_api.get_staged_content_static_file_data(
- self.staged_content.id,
- original_filename,
- )
- if not file_data:
- log.error(
- f"Staged content {self.staged_content.id} included referenced "
- f"file {original_filename}, but no file data was found."
- )
- continue
-
- filename = f"static/{file_basename}"
- media_type_str, _ = mimetypes.guess_type(filename)
- if not media_type_str:
- media_type_str = "application/octet-stream"
-
- media_type = authoring_api.get_or_create_media_type(media_type_str)
- content = authoring_api.get_or_create_file_content(
- self.learning_package.id,
- media_type.id,
- data=file_data,
- created=created_at,
- )
-
- try:
- authoring_api.create_component_version_content(component_version.pk, content.id, key=filename)
- except IntegrityError:
- pass # Content already exists
-
-
-def import_from_staged_content(
- import_event: Import,
- usage_key_string: str,
- target_learning_package: 'LearningPackage',
- staged_content: 'StagedContent',
- composition_level: str,
- override: bool = False,
-) -> list[PublishableVersionWithMapping]:
- """
- Import staged content to a library from staged content.
-
- Returns a list of PublishableVersionWithMappings created during the import.
- """
- import_client = ImportClient(
- import_event,
- usage_key_string,
- target_learning_package,
- staged_content,
- composition_level,
- override,
- )
- return import_client.import_from_staged_content()
-
-
-def get_or_create_publishable_entity_mapping(usage_key, component) -> tuple[PublishableEntityMapping, bool]:
- """
- Creates a mapping between the source usage key and the target publishable entity.
- """
- if isinstance(component, Container):
- target_package = component.publishable_entity.learning_package
- else:
- target_package = component.learning_package
- return PublishableEntityMapping.objects.get_or_create(
- source_usage_key=usage_key,
- target_entity=component.publishable_entity,
- target_package=target_package,
- )
-
-
-def get_usage_key_string_from_staged_content(staged_content: 'StagedContent', block_id: str) -> str | None:
- """
- Get the usage ID from a staged content by block ID.
- """
- if staged_content.tags is None:
- return None
- return next((block_usage_id for block_usage_id in staged_content.tags if block_usage_id.endswith(block_id)), None)
-
-
-def get_node_for_usage_key(node: etree._Element, usage_key: UsageKey) -> etree._Element:
- """
- Get the node in an XML tree which matches to the usage key.
- """
- if node.tag == usage_key.block_type and node.get('url_name') == usage_key.block_id:
- return node
-
- for child in node.getchildren():
- found = get_node_for_usage_key(child, usage_key)
- if found is not None:
- return found
-
-
-def get_items_to_import(import_event: Import) -> list['XBlock']:
- """
- Collect items to import from a course.
- """
- items_to_import: list['XBlock'] = []
- if isinstance(import_event.source_key, CourseLocator):
- items_to_import.extend(
- modulestore().get_items(import_event.source_key, qualifiers={"category": "chapter"}) or []
- )
- items_to_import.extend(
- modulestore().get_items(import_event.source_key, qualifiers={"category": "static_tab"}) or []
- )
-
- return items_to_import
-
-
-def cancel_incomplete_old_imports(import_event: Import) -> None:
- """
- Cancel any incomplete imports that have the same target as the current import.
-
- When a new import is created, we want to cancel any other incomplete user imports that have the same target.
- """
- incomplete_user_imports_with_same_target = Import.objects.filter(
- user=import_event.user,
- target_change=import_event.target_change,
- source_key=import_event.source_key,
- staged_content_for_import__isnull=False
- ).exclude(uuid=import_event.uuid)
- for incomplete_import in incomplete_user_imports_with_same_target:
- incomplete_import.set_status(ImportStatus.CANCELED)
diff --git a/cms/djangoapps/import_from_modulestore/tasks.py b/cms/djangoapps/import_from_modulestore/tasks.py
deleted file mode 100644
index 4644b29e4904..000000000000
--- a/cms/djangoapps/import_from_modulestore/tasks.py
+++ /dev/null
@@ -1,101 +0,0 @@
-"""
-Tasks for course to library import.
-"""
-
-from celery import shared_task
-from celery.utils.log import get_task_logger
-from django.db import transaction
-from edx_django_utils.monitoring import set_code_owner_attribute
-
-from openedx_learning.api import authoring as authoring_api
-from openedx_learning.api.authoring_models import LearningPackage
-from openedx.core.djangoapps.content_staging import api as content_staging_api
-
-from .constants import IMPORT_FROM_MODULESTORE_STAGING_PURPOSE
-from .data import ImportStatus
-from .helpers import get_items_to_import, import_from_staged_content
-from .models import Import, PublishableEntityImport, StagedContentForImport
-from .validators import validate_composition_level
-
-log = get_task_logger(__name__)
-
-
-@shared_task
-@set_code_owner_attribute
-def save_legacy_content_to_staged_content_task(import_uuid: str) -> None:
- """
- Save courses to staged content task by sections/chapters.
- """
- import_event = Import.objects.get(uuid=import_uuid)
-
- import_event.clean_related_staged_content()
- import_event.set_status(ImportStatus.STAGING)
- try:
- with transaction.atomic():
- items_to_import = get_items_to_import(import_event)
- for item in items_to_import:
- staged_content = content_staging_api.stage_xblock_temporarily(
- item,
- import_event.user.id,
- purpose=IMPORT_FROM_MODULESTORE_STAGING_PURPOSE,
- )
- StagedContentForImport.objects.create(
- staged_content=staged_content,
- import_event=import_event,
- source_usage_key=item.location
- )
-
- if items_to_import:
- import_event.set_status(ImportStatus.STAGED)
- else:
- import_event.set_status(ImportStatus.STAGING_FAILED)
- except Exception as exc: # pylint: disable=broad-except
- import_event.set_status(ImportStatus.STAGING_FAILED)
- raise exc
-
-
-@shared_task
-@set_code_owner_attribute
-def import_staged_content_to_library_task(
- usage_key_strings: list[str],
- import_uuid: str,
- learning_package_id: int,
- user_id: int,
- composition_level: str,
- override: bool,
-) -> None:
- """
- Import staged content to a library task.
- """
- validate_composition_level(composition_level)
-
- import_event = Import.objects.get(uuid=import_uuid, status=ImportStatus.STAGED, user_id=user_id)
- target_learning_package = LearningPackage.objects.get(id=learning_package_id)
-
- imported_publishable_versions = []
- with authoring_api.bulk_draft_changes_for(learning_package_id=learning_package_id) as change_log:
- try:
- for usage_key_string in usage_key_strings:
- staged_content_for_import = import_event.staged_content_for_import.get(
- source_usage_key=usage_key_string
- )
- publishable_versions = import_from_staged_content(
- import_event,
- usage_key_string,
- target_learning_package,
- staged_content_for_import.staged_content,
- composition_level,
- override,
- )
- imported_publishable_versions.extend(publishable_versions)
- except: # pylint: disable=bare-except
- import_event.set_status(ImportStatus.IMPORTING_FAILED)
- raise
-
- import_event.set_status(ImportStatus.IMPORTED)
- for imported_component_version in imported_publishable_versions:
- PublishableEntityImport.objects.create(
- import_event=import_event,
- resulting_mapping=imported_component_version.mapping,
- resulting_change=change_log.records.get(entity=imported_component_version.mapping.target_entity),
- )
diff --git a/cms/djangoapps/import_from_modulestore/tests/__init__.py b/cms/djangoapps/import_from_modulestore/tests/__init__.py
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/cms/djangoapps/import_from_modulestore/tests/factories.py b/cms/djangoapps/import_from_modulestore/tests/factories.py
deleted file mode 100644
index 368cc0ed94ff..000000000000
--- a/cms/djangoapps/import_from_modulestore/tests/factories.py
+++ /dev/null
@@ -1,28 +0,0 @@
-"""
-Factories for Import model.
-"""
-
-import uuid
-
-import factory
-from factory.django import DjangoModelFactory
-from opaque_keys.edx.keys import CourseKey
-
-from common.djangoapps.student.tests.factories import UserFactory
-from cms.djangoapps.import_from_modulestore.models import Import
-
-
-class ImportFactory(DjangoModelFactory):
- """
- Factory for Import model.
- """
-
- class Meta:
- model = Import
-
- @factory.lazy_attribute
- def source_key(self):
- return CourseKey.from_string(f'course-v1:edX+DemoX+{self.uuid}')
-
- uuid = factory.LazyFunction(lambda: str(uuid.uuid4()))
- user = factory.SubFactory(UserFactory)
diff --git a/cms/djangoapps/import_from_modulestore/tests/test_api.py b/cms/djangoapps/import_from_modulestore/tests/test_api.py
deleted file mode 100644
index 62fe2e4159a9..000000000000
--- a/cms/djangoapps/import_from_modulestore/tests/test_api.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""
-Test cases for import_from_modulestore.api module.
-"""
-from unittest.mock import patch
-
-import pytest
-from opaque_keys.edx.keys import CourseKey
-from organizations.models import Organization
-
-from common.djangoapps.student.tests.factories import UserFactory
-from cms.djangoapps.import_from_modulestore.api import import_staged_content_to_library, stage_content_for_import
-from cms.djangoapps.import_from_modulestore.data import ImportStatus
-from cms.djangoapps.import_from_modulestore.models import Import
-from openedx.core.djangoapps.content_libraries import api as content_libraries_api
-from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
-from .factories import ImportFactory
-
-
-@pytest.mark.django_db
-class TestCourseToLibraryImportAPI(ModuleStoreTestCase):
- """
- Test cases for Import API.
- """
-
- def setUp(self):
- super().setUp()
-
- _library_metadata = content_libraries_api.create_library(
- org=Organization.objects.create(name='Organization 1', short_name='org1'),
- slug='lib_1',
- title='Library Org 1',
- description='This is a library from Org 1',
- )
- self.library = content_libraries_api.ContentLibrary.objects.get_by_key(_library_metadata.key)
-
- def test_stage_content_for_import(self):
- """
- Test stage_content_for_import function.
- """
- course_id = "course-v1:edX+DemoX+Demo_Course"
- user = UserFactory()
- stage_content_for_import(course_id, user.id)
-
- import_event = Import.objects.get()
- assert import_event.source_key == CourseKey.from_string(course_id)
- assert import_event.user_id == user.id
- assert import_event.status == ImportStatus.NOT_STARTED
-
- def test_import_staged_content_to_library(self):
- """
- Test import_staged_content_to_library function with different override values.
- """
- import_event = ImportFactory(
- source_key=CourseKey.from_string("course-v1:edX+DemoX+Demo_Course"),
- )
- usage_ids = [
- "block-v1:edX+DemoX+Demo_Course+type@chapter+block@123",
- "block-v1:edX+DemoX+Demo_Course+type@chapter+block@456",
- ]
- override = False
-
- with patch(
- "cms.djangoapps.import_from_modulestore.api.import_staged_content_to_library_task"
- ) as import_staged_content_to_library_task_mock:
- import_staged_content_to_library(
- usage_ids,
- import_event.uuid,
- self.library.learning_package.id,
- import_event.user.id,
- "xblock",
- override
- )
-
- import_staged_content_to_library_task_mock.apply_async.assert_called_once_with(
- kwargs={
- "usage_key_strings": usage_ids,
- "import_uuid": import_event.uuid,
- "learning_package_id": self.library.learning_package.id,
- "user_id": import_event.user.id,
- "composition_level": "xblock",
- "override": override,
- },
- )
-
- def test_import_staged_content_to_library_invalid_usage_key(self):
- """
- Test import_staged_content_to_library function with not chapter usage keys.
- """
- import_event = ImportFactory(
- source_key=CourseKey.from_string("course-v1:edX+DemoX+Demo_Course"),
- )
- usage_ids = [
- "block-v1:edX+DemoX+Demo_Course+type@problem+block@123",
- "block-v1:edX+DemoX+Demo_Course+type@vertical+block@456",
- ]
-
- with patch(
- "cms.djangoapps.import_from_modulestore.api.import_staged_content_to_library_task"
- ) as import_staged_content_to_library_task_mock:
- with self.assertRaises(ValueError):
- import_staged_content_to_library(
- usage_ids,
- import_event.uuid,
- self.library.learning_package.id,
- import_event.user.id,
- "xblock",
- False
- )
- import_staged_content_to_library_task_mock.apply_async.assert_not_called()
diff --git a/cms/djangoapps/import_from_modulestore/tests/test_helpers.py b/cms/djangoapps/import_from_modulestore/tests/test_helpers.py
deleted file mode 100644
index 1d2ce26867aa..000000000000
--- a/cms/djangoapps/import_from_modulestore/tests/test_helpers.py
+++ /dev/null
@@ -1,396 +0,0 @@
-"""
-Tests for the import_from_modulestore helper functions.
-"""
-import ddt
-from organizations.models import Organization
-from unittest import mock
-from unittest.mock import patch
-
-from lxml import etree
-from openedx_learning.api.authoring_models import LearningPackage
-
-from cms.djangoapps.import_from_modulestore import api
-from cms.djangoapps.import_from_modulestore.helpers import ImportClient
-from common.djangoapps.student.tests.factories import UserFactory
-
-from openedx.core.djangoapps.content_libraries import api as content_libraries_api
-from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
-from xmodule.modulestore.tests.factories import CourseFactory, BlockFactory
-
-
-@ddt.ddt
-class TestImportClient(ModuleStoreTestCase):
- """
- Functional tests for the ImportClient class.
- """
-
- def setUp(self):
- super().setUp()
- self.library = content_libraries_api.create_library(
- org=Organization.objects.create(name='Organization 1', short_name='org1'),
- slug='lib_1',
- title='Library Org 1',
- description='This is a library from Org 1',
- )
- self.learning_package = LearningPackage.objects.get(id=self.library.learning_package_id)
- self.user = UserFactory()
- self.course = CourseFactory.create()
- self.chapter = BlockFactory.create(category='chapter', parent=self.course, display_name='Chapter')
- self.sequential = BlockFactory.create(category='sequential', parent=self.chapter, display_name='Sequential')
- self.vertical = BlockFactory.create(category='vertical', parent=self.sequential, display_name='Vertical')
- self.problem = BlockFactory.create(
- category='problem',
- parent=self.vertical,
- display_name='Problem',
- data="""""",
- )
- self.video = BlockFactory.create(
- category='video',
- parent=self.vertical,
- display_name='Video',
- data="""""",
- )
- with self.captureOnCommitCallbacks(execute=True):
- self.import_event = api.stage_content_for_import(source_key=self.course.id, user_id=self.user.id)
- self.parser = etree.XMLParser(strip_cdata=False)
-
- def test_import_from_staged_content(self):
- expected_imported_xblocks = [self.video, self.problem]
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- staged_content = staged_content_for_import.staged_content
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=str(self.chapter.location),
- composition_level='xblock',
- override=False
- )
-
- import_client.import_from_staged_content()
-
- self.assertEqual(self.learning_package.content_set.count(), len(expected_imported_xblocks))
-
- @patch('cms.djangoapps.import_from_modulestore.helpers.ImportClient._process_import')
- def test_import_from_staged_content_block_not_found(self, mocked_process_import):
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- staged_content = staged_content_for_import.staged_content
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import='block-v1:edX+Demo+2025+type@chapter+block@12345',
- composition_level='xblock',
- override=False
- )
-
- import_client.import_from_staged_content()
-
- self.assertTrue(not self.learning_package.content_set.count())
- mocked_process_import.assert_not_called()
-
- @ddt.data(
- 'chapter',
- 'sequential',
- 'vertical'
- )
- def test_create_container(self, block_lvl):
- container_to_import = getattr(self, block_lvl)
- block_usage_key_to_import = str(container_to_import.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content_for_import.staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='xblock',
- override=False
- )
- import_client.get_or_create_container(
- container_to_import.category,
- container_to_import.location.block_id,
- container_to_import.display_name,
- str(container_to_import.location)
- )
-
- self.assertEqual(self.learning_package.publishable_entities.count(), 1)
-
- def test_create_container_with_xblock(self):
- block_usage_key_to_import = str(self.problem.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content_for_import.staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='xblock',
- override=False
- )
- with self.assertRaises(ValueError):
- import_client.get_or_create_container(
- self.problem.category,
- self.problem.location.block_id,
- self.problem.display_name,
- str(self.problem.location),
- )
-
- @ddt.data('chapter', 'sequential', 'vertical')
- def test_process_import_with_complicated_blocks(self, block_lvl):
- container_to_import = getattr(self, block_lvl)
- block_usage_key_to_import = str(container_to_import.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- staged_content = staged_content_for_import.staged_content
- expected_imported_xblocks = [self.problem, self.video]
-
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content,
- block_usage_key_to_import=block_usage_key_to_import,
- target_learning_package=self.learning_package,
- composition_level='xblock',
- override=False
- )
- block_to_import = etree.fromstring(staged_content.olx, parser=self.parser)
- # pylint: disable=protected-access
- result = import_client.import_from_staged_content()
-
- self.assertEqual(self.learning_package.content_set.count(), len(expected_imported_xblocks))
- self.assertEqual(len(result), len(expected_imported_xblocks))
-
- @ddt.data('problem', 'video')
- def test_process_import_with_simple_blocks(self, block_type_to_import):
- block_to_import = getattr(self, block_type_to_import)
- block_usage_key_to_import = str(block_to_import.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- expected_imported_xblocks = [block_to_import]
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content_for_import.staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='xblock',
- override=False
- )
-
- block_to_import = etree.fromstring(block_to_import.data, parser=self.parser)
- # pylint: disable=protected-access
- result = import_client._process_import(block_usage_key_to_import, block_to_import)
-
- self.assertEqual(self.learning_package.content_set.count(), len(expected_imported_xblocks))
- self.assertEqual(len(result), len(expected_imported_xblocks))
-
- @ddt.data(True, False)
- def test_process_import_with_override(self, override):
- block_to_import = self.problem
- block_usage_key_to_import = str(block_to_import.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
-
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content_for_import.staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='xblock',
- override=False
- )
-
- block_xml = etree.fromstring(block_to_import.data, parser=self.parser)
- # pylint: disable=protected-access
- result1 = import_client._process_import(block_usage_key_to_import, block_xml)
- self.assertEqual(len(result1), 1)
-
- with self.captureOnCommitCallbacks(execute=True):
- new_import_event = api.stage_content_for_import(source_key=self.course.id, user_id=self.user.id)
-
- staged_content_for_import = new_import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- new_staged_content = staged_content_for_import.staged_content
- import_client = ImportClient(
- import_event=new_import_event,
- staged_content=new_staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='xblock',
- override=override
- )
-
- if override:
- modified_data = block_to_import.data.replace('DisplayName', 'ModifiedName')
- modified_block = BlockFactory.create(
- category='problem',
- parent=self.vertical,
- display_name='Modified Problem',
- data=modified_data,
- )
- block_xml = etree.fromstring(modified_block.data, parser=self.parser)
-
- # pylint: disable=protected-access
- result2 = import_client._process_import(block_usage_key_to_import, block_xml)
- self.assertEqual(len(result2), 1)
-
- assert result2[0].publishable_version.title == 'ModifiedName'
- else:
- # pylint: disable=protected-access
- result2 = import_client._process_import(block_usage_key_to_import, block_xml)
- self.assertEqual(result2, [])
-
- @patch('cms.djangoapps.import_from_modulestore.helpers.authoring_api')
- def test_container_override(self, mock_authoring_api):
- container_to_import = self.vertical
- block_usage_key_to_import = str(container_to_import.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- staged_content = staged_content_for_import.staged_content
-
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='vertical',
- override=False
- )
-
- container_version_with_mapping = import_client.get_or_create_container(
- 'vertical',
- container_to_import.location.block_id,
- container_to_import.display_name,
- str(container_to_import.location),
- )
- assert container_version_with_mapping is not None
- assert container_version_with_mapping.publishable_version.title == container_to_import.display_name
-
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='vertical',
- override=True
- )
- container_version_with_mapping = import_client.get_or_create_container(
- 'vertical',
- container_to_import.location.block_id,
- 'New Display Name',
- str(container_to_import.location),
- )
- overrided_container_version = container_version_with_mapping.publishable_version
- assert overrided_container_version is not None
- assert overrided_container_version.title == 'New Display Name'
-
- @ddt.data('xblock', 'vertical')
- def test_composition_levels(self, composition_level):
- if composition_level == 'xblock':
- expected_imported_blocks = [self.problem, self.video]
- else:
- # The vertical block is expected to be imported as a container
- # with the same location as the original vertical block.
- expected_imported_blocks = [self.vertical, self.problem, self.video]
-
- container_to_import = self.vertical
- block_usage_key_to_import = str(container_to_import.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- staged_content = staged_content_for_import.staged_content
-
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level=composition_level,
- override=False
- )
-
- block_xml = etree.fromstring(staged_content.olx, parser=self.parser)
- # pylint: disable=protected-access
- result = import_client._process_import(block_usage_key_to_import, block_xml)
-
- self.assertEqual(len(result), len(expected_imported_blocks))
-
- @patch('cms.djangoapps.import_from_modulestore.helpers.content_staging_api')
- def test_process_staged_content_files(self, mock_content_staging_api):
- block_to_import = self.problem
- block_usage_key_to_import = str(block_to_import.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
- staged_content = staged_content_for_import.staged_content
-
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='xblock',
- override=False
- )
-
- mock_file_data = b'file content'
- mock_file = mock.MagicMock()
- mock_file.filename = 'test.png'
- mock_content_staging_api.get_staged_content_static_files.return_value = [mock_file]
- mock_content_staging_api.get_staged_content_static_file_data.return_value = mock_file_data
-
- modified_data = '
'
- modified_block = BlockFactory.create(
- category='problem',
- parent=self.vertical,
- display_name='Problem With Image',
- data=modified_data,
- )
- block_xml = etree.fromstring(modified_data, parser=self.parser)
-
- # pylint: disable=protected-access
- import_client._create_block_in_library(block_xml, modified_block.location)
- mock_content_staging_api.get_staged_content_static_file_data.assert_called_once_with(
- staged_content.id, 'test.png'
- )
-
- def test_update_container_components(self):
- container_to_import = self.vertical
- block_usage_key_to_import = str(container_to_import.location)
- staged_content_for_import = self.import_event.staged_content_for_import.get(
- source_usage_key=self.chapter.location
- )
-
- import_client = ImportClient(
- import_event=self.import_event,
- staged_content=staged_content_for_import.staged_content,
- target_learning_package=self.learning_package,
- block_usage_key_to_import=block_usage_key_to_import,
- composition_level='container',
- override=False
- )
-
- with patch('cms.djangoapps.import_from_modulestore.helpers.authoring_api') as mock_authoring_api:
- mock_container_version = mock.MagicMock()
- mock_component_version1 = mock.MagicMock()
- mock_component_version2 = mock.MagicMock()
- mock_component_versions = [mock_component_version1, mock_component_version2]
-
- # pylint: disable=protected-access
- import_client._update_container_components(mock_container_version, mock_component_versions)
-
- mock_authoring_api.create_next_container_version.assert_called_once()
- call_args = mock_authoring_api.create_next_container_version.call_args[1]
- self.assertEqual(call_args['container_pk'], mock_container_version.container.pk)
- self.assertEqual(call_args['title'], mock_container_version.title)
- self.assertEqual(call_args['created_by'], self.user.id)
diff --git a/cms/djangoapps/import_from_modulestore/tests/test_tasks.py b/cms/djangoapps/import_from_modulestore/tests/test_tasks.py
deleted file mode 100644
index 8c24fa95c1cc..000000000000
--- a/cms/djangoapps/import_from_modulestore/tests/test_tasks.py
+++ /dev/null
@@ -1,169 +0,0 @@
-"""
-Tests for tasks in import_from_modulestore app.
-"""
-from django.core.exceptions import ObjectDoesNotExist
-from organizations.models import Organization
-from openedx_learning.api.authoring_models import LearningPackage
-from unittest.mock import patch
-
-from cms.djangoapps.import_from_modulestore.data import ImportStatus
-from cms.djangoapps.import_from_modulestore.tasks import (
- import_staged_content_to_library_task,
- save_legacy_content_to_staged_content_task,
-)
-from openedx.core.djangoapps.content_libraries import api as content_libraries_api
-from openedx.core.djangoapps.content_libraries.api import ContentLibrary
-from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
-from xmodule.modulestore.tests.factories import CourseFactory, BlockFactory
-
-from .factories import ImportFactory
-
-
-class ImportCourseToLibraryMixin(ModuleStoreTestCase):
- """
- Mixin for setting up data for tests.
- """
-
- def setUp(self):
- super().setUp()
-
- self.library = content_libraries_api.create_library(
- org=Organization.objects.create(name='Organization 1', short_name='org1'),
- slug='lib_1',
- title='Library Org 1',
- description='This is a library from Org 1',
- )
- self.content_library = ContentLibrary.objects.get_by_key(self.library.key)
-
- self.course = CourseFactory.create()
- self.chapter = BlockFactory.create(category='chapter', parent=self.course, display_name='Chapter 1')
- self.sequential = BlockFactory.create(category='sequential', parent=self.chapter, display_name='Sequential 1')
- self.vertical = BlockFactory.create(category='vertical', parent=self.sequential, display_name='Vertical 1')
- self.video = BlockFactory.create(category='video', parent=self.vertical, display_name='Video 1')
- self.problem = BlockFactory.create(category='problem', parent=self.vertical, display_name='Problem 1')
-
- # self.course2 = CourseFactory.create()
- # self.chapter2 = BlockFactory.create(category='chapter', parent=self.course, display_name='Chapter 2')
- self.chapter2 = BlockFactory.create(category='chapter', parent=self.course, display_name='Chapter 2')
- self.sequential2 = BlockFactory.create(category='sequential', parent=self.chapter2, display_name='Sequential 2')
- self.vertical2 = BlockFactory.create(category='vertical', parent=self.sequential2, display_name='Vertical 2')
- self.video2 = BlockFactory.create(category='video', parent=self.vertical2, display_name='Video 2')
- self.problem2 = BlockFactory.create(category='problem', parent=self.vertical2, display_name='Problem 2')
-
- self.import_event = ImportFactory(source_key=self.course.id)
- self.user = self.import_event.user
-
-
-class TestSaveCourseSectionsToStagedContentTask(ImportCourseToLibraryMixin):
- """
- Test cases for save_course_sections_to_staged_content_task.
- """
-
- def test_save_legacy_content_to_staged_content_task(self):
- """
- End-to-end test for save_legacy_content_to_staged_content_task.
- """
- course_chapters_to_import = [self.chapter, self.chapter2]
- save_legacy_content_to_staged_content_task(self.import_event.uuid)
-
- self.import_event.refresh_from_db()
- self.assertEqual(self.import_event.staged_content_for_import.count(), len(course_chapters_to_import))
- self.assertEqual(self.import_event.status, ImportStatus.STAGED)
-
- def test_old_staged_content_deletion_before_save_new(self):
- """ Checking that repeated saving of the same content does not create duplicates. """
- course_chapters_to_import = [self.chapter, self.chapter2]
-
- save_legacy_content_to_staged_content_task(self.import_event.uuid)
-
- self.assertEqual(self.import_event.staged_content_for_import.count(), len(course_chapters_to_import))
-
- save_legacy_content_to_staged_content_task(self.import_event.uuid)
-
- self.assertEqual(self.import_event.staged_content_for_import.count(), len(course_chapters_to_import))
-
-
-class TestImportLibraryFromStagedContentTask(ImportCourseToLibraryMixin):
- """
- Test cases for import_staged_content_to_library_task.
- """
-
- def _is_imported(self, library, xblock):
- library_learning_package = LearningPackage.objects.get(id=library.learning_package_id)
- self.assertTrue(library_learning_package.content_set.filter(text__icontains=xblock.display_name).exists())
-
- def test_import_staged_content_to_library_task(self):
- """ End-to-end test for import_staged_content_to_library_task. """
- library_learning_package = LearningPackage.objects.get(id=self.library.learning_package_id)
- self.assertEqual(library_learning_package.content_set.count(), 0)
- expected_imported_xblocks = [self.problem, self.problem2, self.video, self.video2]
- save_legacy_content_to_staged_content_task(self.import_event.uuid)
-
- import_staged_content_to_library_task(
- [str(self.chapter.location), str(self.chapter2.location)],
- self.import_event.uuid,
- self.content_library.learning_package.id,
- self.user.id,
- 'component',
- override=True
- )
-
- self.import_event.refresh_from_db()
- self.assertEqual(self.import_event.status, ImportStatus.IMPORTED)
-
- for xblock in expected_imported_xblocks:
- self._is_imported(self.library, xblock)
-
- library_learning_package.refresh_from_db()
- self.assertEqual(library_learning_package.content_set.count(), len(expected_imported_xblocks))
- self.assertEqual(self.import_event.publishableentityimport_set.count(), len(expected_imported_xblocks))
-
- @patch('cms.djangoapps.import_from_modulestore.tasks.import_from_staged_content')
- def test_import_library_block_not_found(self, mock_import_from_staged_content):
- """ Test that if a block is not found in the staged content, it is not imported. """
- non_existent_usage_ids = ['block-v1:edX+Demo+2023+type@vertical+block@12345']
- save_legacy_content_to_staged_content_task(self.import_event.uuid)
- with self.allow_transaction_exception():
- with self.assertRaises(ObjectDoesNotExist):
- import_staged_content_to_library_task(
- non_existent_usage_ids,
- str(self.import_event.uuid),
- self.content_library.learning_package.id,
- self.user.id,
- 'component',
- override=True,
- )
- mock_import_from_staged_content.assert_not_called()
-
- def test_cannot_import_staged_content_twice(self):
- """
- Tests if after importing staged content into the library,
- the staged content is deleted and cannot be imported again.
- """
- chapters_to_import = [self.chapter, self.chapter2]
- expected_imported_xblocks = [self.problem, self.video]
- save_legacy_content_to_staged_content_task(self.import_event.uuid)
-
- self.import_event.refresh_from_db()
- self.assertEqual(self.import_event.staged_content_for_import.count(), len(chapters_to_import))
- self.assertEqual(self.import_event.status, ImportStatus.STAGED)
-
- import_staged_content_to_library_task(
- [str(self.chapter.location)],
- str(self.import_event.uuid),
- self.content_library.learning_package.id,
- self.user.id,
- 'component',
- override=True,
- )
-
- for xblock in expected_imported_xblocks:
- self._is_imported(self.library, xblock)
-
- library_learning_package = LearningPackage.objects.get(id=self.library.learning_package_id)
- self.assertEqual(library_learning_package.content_set.count(), len(expected_imported_xblocks))
-
- self.import_event.refresh_from_db()
- self.assertEqual(self.import_event.status, ImportStatus.IMPORTED)
- self.assertTrue(not self.import_event.staged_content_for_import.exists())
- self.assertEqual(self.import_event.publishableentityimport_set.count(), len(expected_imported_xblocks))
diff --git a/cms/djangoapps/import_from_modulestore/tests/test_validators.py b/cms/djangoapps/import_from_modulestore/tests/test_validators.py
deleted file mode 100644
index 961d1cc81ba7..000000000000
--- a/cms/djangoapps/import_from_modulestore/tests/test_validators.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""
-Tests for import_from_modulestore validators
-"""
-
-from typing import get_args
-
-from django.test import TestCase
-import pytest
-
-from cms.djangoapps.import_from_modulestore.validators import (
- validate_composition_level,
-)
-from cms.djangoapps.import_from_modulestore.data import CompositionLevel
-
-
-class TestValidateCompositionLevel(TestCase):
- """
- Test cases for validate_composition_level function.
- Case 1: Valid composition level
- Case 2: Invalid composition level
- """
-
- def test_valid_composition_level(self):
- for level in get_args(CompositionLevel):
- # Should not raise an exception for valid levels
- validate_composition_level(level)
-
- def test_invalid_composition_level(self):
- with pytest.raises(ValueError) as exc:
- validate_composition_level('invalid_composition_level')
- assert 'Invalid composition level: invalid_composition_level' in str(exc.value)
diff --git a/cms/djangoapps/import_from_modulestore/validators.py b/cms/djangoapps/import_from_modulestore/validators.py
deleted file mode 100644
index ecf0c72e08e8..000000000000
--- a/cms/djangoapps/import_from_modulestore/validators.py
+++ /dev/null
@@ -1,26 +0,0 @@
-"""
-Validators for the import_from_modulestore app.
-"""
-from typing import Sequence
-
-from opaque_keys.edx.keys import UsageKey
-
-from .data import CompositionLevel
-
-
-def validate_usage_keys_to_import(usage_keys: Sequence[str | UsageKey]):
- """
- Validate the usage keys to import.
-
- Currently, supports importing from the modulestore only by chapters.
- """
- for usage_key in usage_keys:
- if isinstance(usage_key, str):
- usage_key = UsageKey.from_string(usage_key)
- if usage_key.block_type != 'chapter':
- raise ValueError(f'Importing from modulestore only supports chapters, not {usage_key.block_type}')
-
-
-def validate_composition_level(composition_level):
- if composition_level not in CompositionLevel.values():
- raise ValueError(f'Invalid composition level: {composition_level}')