tests are failings and complaining related objects doest not exists in User table. Create object in test setup to fix it. In another fix article id was giving integrity error. Fixing task test.
166 lines
6.7 KiB
Python
166 lines
6.7 KiB
Python
"""
|
|
Unit tests for course import and export Celery tasks
|
|
"""
|
|
|
|
|
|
import copy
|
|
import json
|
|
from unittest import mock
|
|
from uuid import uuid4
|
|
|
|
from django.conf import settings
|
|
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
|
from django.test.utils import override_settings
|
|
from opaque_keys.edx.locator import CourseLocator
|
|
from organizations.models import OrganizationCourse
|
|
from organizations.tests.factories import OrganizationFactory
|
|
from user_tasks.models import UserTaskArtifact, UserTaskStatus
|
|
|
|
from cms.djangoapps.contentstore.tasks import export_olx, rerun_course
|
|
from cms.djangoapps.contentstore.tests.test_libraries import LibraryTestCase
|
|
from cms.djangoapps.contentstore.tests.utils import CourseTestCase
|
|
from common.djangoapps.course_action_state.models import CourseRerunState
|
|
from common.djangoapps.student.tests.factories import UserFactory
|
|
from openedx.core.djangoapps.embargo.models import Country, CountryAccessRule, RestrictedCourse
|
|
from xmodule.modulestore.django import modulestore
|
|
|
|
TEST_DATA_CONTENTSTORE = copy.deepcopy(settings.CONTENTSTORE)
|
|
TEST_DATA_CONTENTSTORE['DOC_STORE_CONFIG']['db'] = 'test_xcontent_%s' % uuid4().hex
|
|
|
|
|
|
def side_effect_exception(*args, **kwargs):
|
|
"""
|
|
Side effect for mocking which raises an exception
|
|
"""
|
|
raise Exception('Boom!')
|
|
|
|
|
|
@override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE)
|
|
class ExportCourseTestCase(CourseTestCase):
|
|
"""
|
|
Tests of the export_olx task applied to courses
|
|
"""
|
|
|
|
def test_success(self):
|
|
"""
|
|
Verify that a routine course export task succeeds
|
|
"""
|
|
key = str(self.course.location.course_key)
|
|
result = export_olx.delay(self.user.id, key, 'en')
|
|
status = UserTaskStatus.objects.get(task_id=result.id)
|
|
self.assertEqual(status.state, UserTaskStatus.SUCCEEDED)
|
|
artifacts = UserTaskArtifact.objects.filter(status=status)
|
|
self.assertEqual(len(artifacts), 1)
|
|
output = artifacts[0]
|
|
self.assertEqual(output.name, 'Output')
|
|
|
|
@mock.patch('cms.djangoapps.contentstore.tasks.export_course_to_xml', side_effect=side_effect_exception)
|
|
def test_exception(self, mock_export): # pylint: disable=unused-argument
|
|
"""
|
|
The export task should fail gracefully if an exception is thrown
|
|
"""
|
|
key = str(self.course.location.course_key)
|
|
result = export_olx.delay(self.user.id, key, 'en')
|
|
self._assert_failed(result, json.dumps({'raw_error_msg': 'Boom!'}))
|
|
|
|
@mock.patch('cms.djangoapps.contentstore.tasks.User.objects.get', side_effect=User.DoesNotExist)
|
|
def test_invalid_user_id(self, mock_raise_exc): # pylint: disable=unused-argument
|
|
"""
|
|
Verify that attempts to export a course as an invalid user fail
|
|
"""
|
|
user = UserFactory(id=User.objects.order_by('-id').first().pk + 100)
|
|
key = str(self.course.location.course_key)
|
|
result = export_olx.delay(user.id, key, 'en')
|
|
self._assert_failed(result, f'Unknown User ID: {user.id}')
|
|
|
|
def test_non_course_author(self):
|
|
"""
|
|
Verify that users who aren't authors of the course are unable to export it
|
|
"""
|
|
_, nonstaff_user = self.create_non_staff_authed_user_client()
|
|
key = str(self.course.location.course_key)
|
|
result = export_olx.delay(nonstaff_user.id, key, 'en')
|
|
self._assert_failed(result, 'Permission denied')
|
|
|
|
def _assert_failed(self, task_result, error_message):
|
|
"""
|
|
Verify that a task failed with the specified error message
|
|
"""
|
|
status = UserTaskStatus.objects.get(task_id=task_result.id)
|
|
self.assertEqual(status.state, UserTaskStatus.FAILED)
|
|
artifacts = UserTaskArtifact.objects.filter(status=status)
|
|
self.assertEqual(len(artifacts), 1)
|
|
error = artifacts[0]
|
|
self.assertEqual(error.name, 'Error')
|
|
self.assertEqual(error.text, error_message)
|
|
|
|
|
|
@override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE)
|
|
class ExportLibraryTestCase(LibraryTestCase):
|
|
"""
|
|
Tests of the export_olx task applied to libraries
|
|
"""
|
|
|
|
def test_success(self):
|
|
"""
|
|
Verify that a routine library export task succeeds
|
|
"""
|
|
key = str(self.lib_key)
|
|
result = export_olx.delay(self.user.id, key, 'en')
|
|
status = UserTaskStatus.objects.get(task_id=result.id)
|
|
self.assertEqual(status.state, UserTaskStatus.SUCCEEDED)
|
|
artifacts = UserTaskArtifact.objects.filter(status=status)
|
|
self.assertEqual(len(artifacts), 1)
|
|
output = artifacts[0]
|
|
self.assertEqual(output.name, 'Output')
|
|
|
|
|
|
@override_settings(CONTENTSTORE=TEST_DATA_CONTENTSTORE)
|
|
class RerunCourseTaskTestCase(CourseTestCase): # lint-amnesty, pylint: disable=missing-class-docstring
|
|
def _rerun_course(self, old_course_key, new_course_key):
|
|
CourseRerunState.objects.initiated(old_course_key, new_course_key, self.user, 'Test Re-run')
|
|
rerun_course(str(old_course_key), str(new_course_key), self.user.id)
|
|
|
|
def test_success(self):
|
|
""" The task should clone the OrganizationCourse and RestrictedCourse data. """
|
|
old_course_key = self.course.id
|
|
new_course_key = CourseLocator(org=old_course_key.org, course=old_course_key.course, run='rerun')
|
|
|
|
old_course_id = str(old_course_key)
|
|
new_course_id = str(new_course_key)
|
|
|
|
organization = OrganizationFactory(short_name=old_course_key.org)
|
|
OrganizationCourse.objects.create(course_id=old_course_id, organization=organization)
|
|
|
|
restricted_course = RestrictedCourse.objects.create(course_key=self.course.id)
|
|
restricted_country = Country.objects.create(country='US')
|
|
|
|
CountryAccessRule.objects.create(
|
|
rule_type=CountryAccessRule.BLACKLIST_RULE,
|
|
restricted_course=restricted_course,
|
|
country=restricted_country
|
|
)
|
|
|
|
# Run the task!
|
|
self._rerun_course(old_course_key, new_course_key)
|
|
|
|
# Verify the new course run exists
|
|
course = modulestore().get_course(new_course_key)
|
|
self.assertIsNotNone(course)
|
|
|
|
# Verify the OrganizationCourse is cloned
|
|
self.assertEqual(OrganizationCourse.objects.count(), 2)
|
|
# This will raise an error if the OrganizationCourse object was not cloned
|
|
OrganizationCourse.objects.get(course_id=new_course_id, organization=organization)
|
|
|
|
# Verify the RestrictedCourse and related objects are cloned
|
|
self.assertEqual(RestrictedCourse.objects.count(), 2)
|
|
restricted_course = RestrictedCourse.objects.get(course_key=new_course_key)
|
|
|
|
self.assertEqual(CountryAccessRule.objects.count(), 2)
|
|
CountryAccessRule.objects.get(
|
|
rule_type=CountryAccessRule.BLACKLIST_RULE,
|
|
restricted_course=restricted_course,
|
|
country=restricted_country
|
|
)
|