143 lines
6.0 KiB
Python
143 lines
6.0 KiB
Python
"""
|
|
Tests for signals.py
|
|
"""
|
|
|
|
from unittest.mock import patch
|
|
from django.test.utils import override_settings
|
|
from django.conf import settings
|
|
|
|
from edx_toggles.toggles.testutils import override_waffle_flag
|
|
from xmodule.modulestore.django import SignalHandler
|
|
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
|
from xmodule.modulestore.tests.factories import CourseFactory, BlockFactory
|
|
from common.djangoapps.util.storage import resolve_storage_backend
|
|
from storages.backends.s3boto3 import S3Boto3Storage
|
|
from django.core.files.storage import storages
|
|
|
|
from .signals import export_course_metadata
|
|
from .toggles import EXPORT_COURSE_METADATA_FLAG
|
|
|
|
|
|
@override_waffle_flag(EXPORT_COURSE_METADATA_FLAG, True)
|
|
class TestExportCourseMetadata(SharedModuleStoreTestCase):
|
|
"""
|
|
Tests for the export_course_metadata function
|
|
"""
|
|
ENABLED_SIGNALS = ['course_published']
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
SignalHandler.course_published.disconnect(export_course_metadata)
|
|
self.course = CourseFactory.create(highlights_enabled_for_messaging=True)
|
|
self.course_key = self.course.id
|
|
|
|
def tearDown(self):
|
|
super().tearDown()
|
|
SignalHandler.course_published.disconnect(export_course_metadata)
|
|
|
|
def _create_chapter(self, **kwargs):
|
|
BlockFactory.create(
|
|
parent=self.course,
|
|
category='chapter',
|
|
**kwargs
|
|
)
|
|
|
|
@patch('cms.djangoapps.export_course_metadata.tasks.course_metadata_export_storage')
|
|
@patch('cms.djangoapps.export_course_metadata.tasks.ContentFile')
|
|
def test_happy_path(self, patched_content, patched_storage):
|
|
""" Ensure we call the storage class with the correct parameters and course metadata """
|
|
all_highlights = [["week1highlight1", "week1highlight2"], ["week1highlight1", "week1highlight2"], [], []]
|
|
with self.store.bulk_operations(self.course_key):
|
|
for week_highlights in all_highlights:
|
|
self._create_chapter(highlights=week_highlights)
|
|
SignalHandler.course_published.connect(export_course_metadata)
|
|
SignalHandler.course_published.send(sender=None, course_key=self.course_key)
|
|
patched_content.assert_called_once_with(
|
|
b'{"highlights": [["week1highlight1", "week1highlight2"], ["week1highlight1", "week1highlight2"], [], []]}'
|
|
)
|
|
patched_storage.save.assert_called_once_with(
|
|
f'course_metadata_export/{self.course_key}.json', patched_content.return_value
|
|
)
|
|
|
|
@override_settings(
|
|
COURSE_METADATA_EXPORT_STORAGE="cms.djangoapps.export_course_metadata.storage.CourseMetadataExportS3Storage",
|
|
STORAGES={
|
|
'default': {
|
|
'BACKEND': "django.core.files.storage.FileSystemStorage"
|
|
}
|
|
}
|
|
)
|
|
def test_resolve_default_storage(self):
|
|
""" Ensure the default storage is invoked, even if course export storage is configured """
|
|
storage = storages["default"]
|
|
self.assertEqual(storage.__class__.__name__, "FileSystemStorage")
|
|
|
|
@override_settings(
|
|
COURSE_METADATA_EXPORT_STORAGE="cms.djangoapps.export_course_metadata.storage.CourseMetadataExportS3Storage",
|
|
STORAGES={
|
|
"default": {
|
|
"BACKEND": "django.core.files.storage.FileSystemStorage"
|
|
}
|
|
},
|
|
COURSE_METADATA_EXPORT_BUCKET="bucket_name_test"
|
|
)
|
|
def test_resolve_happy_path_storage(self):
|
|
""" Make sure that the correct course export storage is being used """
|
|
storage = resolve_storage_backend(
|
|
storage_key="course_metadata_export_storage",
|
|
legacy_setting_key="COURSE_METADATA_EXPORT_STORAGE"
|
|
)
|
|
self.assertEqual(storage.__class__.__name__, "CourseMetadataExportS3Storage")
|
|
self.assertEqual(storage.bucket_name, "bucket_name_test")
|
|
|
|
@override_settings()
|
|
def test_resolve_storage_with_no_config(self):
|
|
""" If no storage setup is defined, we get FileSystemStorage by default """
|
|
del settings.COURSE_METADATA_EXPORT_STORAGE
|
|
del settings.COURSE_METADATA_EXPORT_BUCKET
|
|
storage = resolve_storage_backend(
|
|
storage_key="course_metadata_export_storage",
|
|
legacy_setting_key="COURSE_METADATA_EXPORT_STORAGE"
|
|
)
|
|
self.assertEqual(storage.__class__.__name__, "FileSystemStorage")
|
|
|
|
@override_settings(
|
|
COURSE_METADATA_EXPORT_STORAGE=None,
|
|
COURSE_METADATA_EXPORT_BUCKET="bucket_name_test",
|
|
STORAGES={
|
|
'course_metadata_export_storage': {
|
|
'BACKEND': 'cms.djangoapps.export_course_metadata.storage.CourseMetadataExportS3Storage',
|
|
'OPTIONS': {}
|
|
}
|
|
}
|
|
)
|
|
def test_resolve_storage_using_django5_settings(self):
|
|
""" Simulating a Django 4 environment using Django 5 Storages configuration """
|
|
storage = resolve_storage_backend(
|
|
storage_key="course_metadata_export_storage",
|
|
legacy_setting_key="COURSE_METADATA_EXPORT_STORAGE"
|
|
)
|
|
self.assertEqual(storage.__class__.__name__, "CourseMetadataExportS3Storage")
|
|
self.assertEqual(storage.bucket_name, "bucket_name_test")
|
|
|
|
@override_settings(
|
|
STORAGES={
|
|
'course_metadata_export_storage': {
|
|
'BACKEND': 'storages.backends.s3boto3.S3Boto3Storage',
|
|
'OPTIONS': {
|
|
'bucket_name': 'bucket_name_test'
|
|
}
|
|
}
|
|
}
|
|
)
|
|
def test_resolve_storage_using_django5_settings_with_options(self):
|
|
""" Ensure we call the storage class with the correct parameters and Django 5 setup """
|
|
del settings.COURSE_METADATA_EXPORT_STORAGE
|
|
del settings.COURSE_METADATA_EXPORT_BUCKET
|
|
storage = resolve_storage_backend(
|
|
storage_key="course_metadata_export_storage",
|
|
legacy_setting_key="COURSE_METADATA_EXPORT_STORAGE"
|
|
)
|
|
self.assertEqual(storage.__class__.__name__, S3Boto3Storage.__name__)
|
|
self.assertEqual(storage.bucket_name, "bucket_name_test")
|