Fix failures caused by removing lms/djangoapps from sys.path
This commit is contained in:
committed by
Calen Pennington
parent
211bd3beb5
commit
4a120a9e26
@@ -20,6 +20,7 @@ from django.utils.translation import ugettext_lazy
|
||||
from path import Path as path
|
||||
|
||||
from openedx.core.release import RELEASE_LINE
|
||||
from xmodule.modulestore.modulestore_settings import update_module_store_settings
|
||||
|
||||
########################## Prod-like settings ###################################
|
||||
# These should be as close as possible to the settings we use in production.
|
||||
@@ -36,6 +37,7 @@ os.environ['REVISION_CFG'] = "{config_root}/revisions.yml".format(config_root=CO
|
||||
|
||||
from .production import * # pylint: disable=wildcard-import, unused-wildcard-import, wrong-import-position
|
||||
|
||||
|
||||
######################### Testing overrides ####################################
|
||||
|
||||
# Redirect to the test_root folder within the repo
|
||||
|
||||
@@ -48,7 +48,7 @@ from datetime import timedelta
|
||||
import lms.envs.common
|
||||
# Although this module itself may not use these imported variables, other dependent modules may.
|
||||
from lms.envs.common import (
|
||||
USE_TZ, ALL_LANGUAGES, update_module_store_settings, ASSET_IGNORE_REGEX,
|
||||
USE_TZ, ALL_LANGUAGES, ASSET_IGNORE_REGEX,
|
||||
PARENTAL_CONSENT_AGE_LIMIT, REGISTRATION_EMAIL_PATTERNS_ALLOWED,
|
||||
# The following PROFILE_IMAGE_* settings are included as they are
|
||||
# indirectly accessed through the email opt-in API, which is
|
||||
@@ -1440,7 +1440,7 @@ INSTALLED_APPS = [
|
||||
# by installed apps.
|
||||
'openedx.core.djangoapps.oauth_dispatch.apps.OAuthDispatchAppConfig',
|
||||
'lms.djangoapps.courseware',
|
||||
'coursewarehistoryextended',
|
||||
'lms.djangoapps.coursewarehistoryextended',
|
||||
'survey.apps.SurveyConfig',
|
||||
'lms.djangoapps.verify_student.apps.VerifyStudentConfig',
|
||||
'completion',
|
||||
@@ -1499,7 +1499,7 @@ INSTALLED_APPS = [
|
||||
'openedx.features.course_duration_limits',
|
||||
'openedx.features.content_type_gating',
|
||||
'openedx.features.discounts',
|
||||
'experiments',
|
||||
'lms.djangoapps.experiments',
|
||||
|
||||
'openedx.core.djangoapps.external_user_ids',
|
||||
# so sample_task is available to celery workers
|
||||
|
||||
@@ -14,7 +14,6 @@ sessions. Assumes structure:
|
||||
# pylint: disable=wildcard-import, unused-wildcard-import
|
||||
|
||||
|
||||
from .common import *
|
||||
import os
|
||||
from uuid import uuid4
|
||||
|
||||
@@ -24,8 +23,12 @@ from path import Path as path
|
||||
from openedx.core.lib.derived import derive_settings
|
||||
from util.db import NoOpMigrationModules
|
||||
|
||||
from xmodule.modulestore.modulestore_settings import update_module_store_settings
|
||||
|
||||
from .common import *
|
||||
|
||||
# import settings from LMS for consistent behavior with CMS
|
||||
from lms.envs.test import (
|
||||
from lms.envs.test import ( # pylint: disable=wrong-import-order
|
||||
COMPREHENSIVE_THEME_DIRS,
|
||||
DEFAULT_FILE_STORAGE,
|
||||
ECOMMERCE_API_URL,
|
||||
|
||||
@@ -44,7 +44,7 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
|
||||
None: None,
|
||||
}
|
||||
|
||||
URLCONF_MODULES = ['verify_student.urls']
|
||||
URLCONF_MODULES = ['lms.djangoapps.verify_student.urls']
|
||||
|
||||
def setUp(self):
|
||||
# Invoke UrlResetMixin
|
||||
|
||||
@@ -40,5 +40,5 @@ INSTALLED_APPS.extend([
|
||||
'course_creators',
|
||||
'xblock_config.apps.XBlockConfig',
|
||||
'user_tasks',
|
||||
'lti_provider'
|
||||
'lms.djangoapps.lti_provider'
|
||||
])
|
||||
|
||||
@@ -254,15 +254,6 @@ for app in os.listdir(six.text_type(root / 'common' / 'djangoapps')):
|
||||
if os.path.isdir(six.text_type(root / path)) and app != 'terrain':
|
||||
modules[path] = path
|
||||
|
||||
# These Django apps under lms don't import correctly with the "lms.djangapps" prefix
|
||||
# Others don't import correctly without it...INSTALLED_APPS entries are inconsistent
|
||||
lms_djangoapps = ['badges', 'branding', 'bulk_email', 'courseware',
|
||||
'coursewarehistoryextended', 'email_marketing', 'experiments', 'lti_provider',
|
||||
'mobile_api', 'notes', 'rss_proxy', 'shoppingcart', 'survey']
|
||||
for app in lms_djangoapps:
|
||||
path = os.path.join('lms', 'djangoapps', app)
|
||||
modules[path] = path
|
||||
|
||||
|
||||
def update_settings_module(service='lms'):
|
||||
"""
|
||||
|
||||
@@ -12,7 +12,7 @@ class BadgesConfig(AppConfig):
|
||||
"""
|
||||
Application Configuration for Badges.
|
||||
"""
|
||||
name = u'badges'
|
||||
name = u'lms.djangoapps.badges'
|
||||
|
||||
def ready(self):
|
||||
"""
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.test import TestCase
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
from branding.api import _footer_business_links, get_footer, get_home_url, get_logo_url
|
||||
from ..api import _footer_business_links, get_footer, get_home_url, get_logo_url
|
||||
from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration
|
||||
|
||||
test_config_disabled_contact_us = { # pylint: disable=invalid-name
|
||||
|
||||
8
lms/djangoapps/bulk_email/apps.py
Normal file
8
lms/djangoapps/bulk_email/apps.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class BulkEmailConfig(AppConfig):
|
||||
"""
|
||||
Application Configuration for bulk_email.
|
||||
"""
|
||||
name = u'lms.djangoapps.bulk_email'
|
||||
@@ -26,7 +26,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
|
||||
from lms.djangoapps.bulk_email.api import get_unsubscribed_link
|
||||
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class TestOptoutCourseEmails(ModuleStoreTestCase):
|
||||
"""
|
||||
Test that optouts are referenced in sending course email.
|
||||
@@ -144,7 +144,7 @@ class TestOptoutCourseEmails(ModuleStoreTestCase):
|
||||
self.assertIn(self.instructor.email, sent_addresses)
|
||||
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class TestACEOptoutCourseEmails(ModuleStoreTestCase):
|
||||
"""
|
||||
Test that optouts are referenced in sending course email.
|
||||
|
||||
@@ -21,8 +21,8 @@ from django.utils.translation import get_language
|
||||
from markupsafe import escape
|
||||
from mock import Mock, patch
|
||||
|
||||
from bulk_email.models import BulkEmailFlag, Optout
|
||||
from bulk_email.tasks import _get_course_email_context, _get_source_address
|
||||
from ..models import BulkEmailFlag, Optout
|
||||
from ..tasks import _get_course_email_context, _get_source_address
|
||||
from course_modes.models import CourseMode
|
||||
|
||||
from lms.djangoapps.courseware.tests.factories import InstructorFactory, StaffFactory
|
||||
@@ -166,7 +166,7 @@ class SendEmailWithMockedUgettextMixin(object):
|
||||
text=text,
|
||||
)
|
||||
|
||||
with patch('bulk_email.tasks._', side_effect=mock_ugettext):
|
||||
with patch('lms.djangoapps.bulk_email.tasks._', side_effect=mock_ugettext):
|
||||
self.client.post(self.send_mail_url, test_email)
|
||||
|
||||
return mail.outbox[0]
|
||||
@@ -229,7 +229,7 @@ class LocalizedFromAddressCourseLangTestCase(SendEmailWithMockedUgettextMixin, E
|
||||
self.assertRegex(message.from_email, 'AR .* Course Staff')
|
||||
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class TestEmailSendFromDashboardMockedHtmlToText(EmailSendFromDashboardTestCase):
|
||||
"""
|
||||
Tests email sending with mocked html_to_text.
|
||||
@@ -249,7 +249,7 @@ class TestEmailSendFromDashboardMockedHtmlToText(EmailSendFromDashboardTestCase)
|
||||
# We should get back a HttpResponseForbidden (status code 403)
|
||||
self.assertContains(response, "Email is not enabled for this course.", status_code=403)
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
def test_send_to_self(self):
|
||||
"""
|
||||
Make sure email send to myself goes to myself.
|
||||
@@ -566,7 +566,7 @@ class TestEmailSendFromDashboardMockedHtmlToText(EmailSendFromDashboardTestCase)
|
||||
self.assertEqual(len(from_email), 61)
|
||||
|
||||
@override_settings(BULK_EMAIL_EMAILS_PER_TASK=3)
|
||||
@patch('bulk_email.tasks.update_subtask_status')
|
||||
@patch('lms.djangoapps.bulk_email.tasks.update_subtask_status')
|
||||
def test_chunked_queries_send_numerous_emails(self, email_mock):
|
||||
"""
|
||||
Test sending a large number of emails, to test the chunked querying
|
||||
|
||||
@@ -41,7 +41,7 @@ class EmailTestException(Exception):
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class TestEmailErrors(ModuleStoreTestCase):
|
||||
"""
|
||||
Test that errors from sending email are handled properly.
|
||||
@@ -75,8 +75,8 @@ class TestEmailErrors(ModuleStoreTestCase):
|
||||
super(TestEmailErrors, cls).tearDownClass()
|
||||
BulkEmailFlag.objects.all().delete()
|
||||
|
||||
@patch('bulk_email.tasks.get_connection', autospec=True)
|
||||
@patch('bulk_email.tasks.send_course_email.retry')
|
||||
@patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True)
|
||||
@patch('lms.djangoapps.bulk_email.tasks.send_course_email.retry')
|
||||
def test_data_err_retry(self, retry, get_conn):
|
||||
"""
|
||||
Test that celery handles transient SMTPDataErrors by retrying.
|
||||
@@ -97,9 +97,9 @@ class TestEmailErrors(ModuleStoreTestCase):
|
||||
exc = kwargs['exc']
|
||||
self.assertIsInstance(exc, SMTPDataError)
|
||||
|
||||
@patch('bulk_email.tasks.get_connection', autospec=True)
|
||||
@patch('bulk_email.tasks.update_subtask_status')
|
||||
@patch('bulk_email.tasks.send_course_email.retry')
|
||||
@patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True)
|
||||
@patch('lms.djangoapps.bulk_email.tasks.update_subtask_status')
|
||||
@patch('lms.djangoapps.bulk_email.tasks.send_course_email.retry')
|
||||
def test_data_err_fail(self, retry, result, get_conn):
|
||||
"""
|
||||
Test that celery handles permanent SMTPDataErrors by failing and not retrying.
|
||||
@@ -130,8 +130,8 @@ class TestEmailErrors(ModuleStoreTestCase):
|
||||
self.assertEqual(subtask_status.failed, expected_fails)
|
||||
self.assertEqual(subtask_status.succeeded, settings.BULK_EMAIL_EMAILS_PER_TASK - expected_fails)
|
||||
|
||||
@patch('bulk_email.tasks.get_connection', autospec=True)
|
||||
@patch('bulk_email.tasks.send_course_email.retry')
|
||||
@patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True)
|
||||
@patch('lms.djangoapps.bulk_email.tasks.send_course_email.retry')
|
||||
def test_disconn_err_retry(self, retry, get_conn):
|
||||
"""
|
||||
Test that celery handles SMTPServerDisconnected by retrying.
|
||||
@@ -151,8 +151,8 @@ class TestEmailErrors(ModuleStoreTestCase):
|
||||
exc = kwargs['exc']
|
||||
self.assertIsInstance(exc, SMTPServerDisconnected)
|
||||
|
||||
@patch('bulk_email.tasks.get_connection', autospec=True)
|
||||
@patch('bulk_email.tasks.send_course_email.retry')
|
||||
@patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True)
|
||||
@patch('lms.djangoapps.bulk_email.tasks.send_course_email.retry')
|
||||
def test_conn_err_retry(self, retry, get_conn):
|
||||
"""
|
||||
Test that celery handles SMTPConnectError by retrying.
|
||||
@@ -173,8 +173,8 @@ class TestEmailErrors(ModuleStoreTestCase):
|
||||
exc = kwargs['exc']
|
||||
self.assertIsInstance(exc, SMTPConnectError)
|
||||
|
||||
@patch('bulk_email.tasks.SubtaskStatus.increment')
|
||||
@patch('bulk_email.tasks.log')
|
||||
@patch('lms.djangoapps.bulk_email.tasks.SubtaskStatus.increment')
|
||||
@patch('lms.djangoapps.bulk_email.tasks.log')
|
||||
def test_nonexistent_email(self, mock_log, result):
|
||||
"""
|
||||
Tests retries when the email doesn't exist
|
||||
@@ -368,5 +368,5 @@ class TestEmailErrors(ModuleStoreTestCase):
|
||||
with self.assertRaises(CourseEmail.DoesNotExist):
|
||||
# we skip the call that updates subtask status, since we've not set up the InstructorTask
|
||||
# for the subtask, and it's not important to the test.
|
||||
with patch('bulk_email.tasks.update_subtask_status'):
|
||||
with patch('lms.djangoapps.bulk_email.tasks.update_subtask_status'):
|
||||
send_course_email(entry_id, bogus_email_id, to_list, global_email_context, subtask_status.to_dict())
|
||||
|
||||
@@ -31,7 +31,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class CourseEmailTest(ModuleStoreTestCase):
|
||||
"""Test the CourseEmail model."""
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class TestOptoutCourseEmailsBySignal(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests that the force_optout_all signal receiver opts the user out of course emails
|
||||
|
||||
@@ -32,8 +32,8 @@ from mock import Mock, patch
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from six.moves import range
|
||||
|
||||
from bulk_email.models import SEND_TO_LEARNERS, SEND_TO_MYSELF, SEND_TO_STAFF, CourseEmail, Optout
|
||||
from bulk_email.tasks import _get_course_email_context
|
||||
from ..models import SEND_TO_LEARNERS, SEND_TO_MYSELF, SEND_TO_STAFF, CourseEmail, Optout
|
||||
from ..tasks import _get_course_email_context
|
||||
from lms.djangoapps.instructor_task.models import InstructorTask
|
||||
from lms.djangoapps.instructor_task.subtasks import SubtaskStatus, update_subtask_status
|
||||
from lms.djangoapps.instructor_task.tasks import send_bulk_course_email
|
||||
@@ -75,7 +75,7 @@ def my_update_subtask_status(entry_id, current_task_id, new_subtask_status):
|
||||
update_subtask_status(entry_id, current_task_id, new_subtask_status)
|
||||
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
"""Tests instructor task that send bulk email."""
|
||||
|
||||
@@ -134,7 +134,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
update_subtask_status(entry_id, bogus_task_id, new_subtask_status)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
with patch('bulk_email.tasks.update_subtask_status', dummy_update_subtask_status):
|
||||
with patch('lms.djangoapps.bulk_email.tasks.update_subtask_status', dummy_update_subtask_status):
|
||||
send_bulk_course_email(task_entry.id, {})
|
||||
|
||||
def _create_students(self, num_students):
|
||||
@@ -194,7 +194,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
num_emails = settings.BULK_EMAIL_EMAILS_PER_TASK
|
||||
# We also send email to the instructor:
|
||||
self._create_students(num_emails - 1)
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([None])
|
||||
self._test_run_with_task(send_bulk_course_email, 'emailed', num_emails, num_emails)
|
||||
|
||||
@@ -203,12 +203,12 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
num_emails = settings.BULK_EMAIL_EMAILS_PER_TASK
|
||||
# We also send email to the instructor:
|
||||
self._create_students(num_emails - 1)
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([None])
|
||||
task_entry = self._test_run_with_task(send_bulk_course_email, 'emailed', num_emails, num_emails)
|
||||
|
||||
# submit the same task a second time, and confirm that it is not run again.
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([Exception("This should not happen!")])
|
||||
parent_status = self._run_task_with_mock_celery(send_bulk_course_email, task_entry.id, task_entry.task_id)
|
||||
self.assertEqual(parent_status.get('total'), num_emails)
|
||||
@@ -224,7 +224,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
student = students[0]
|
||||
student.is_active = False
|
||||
student.save()
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([None])
|
||||
self._test_run_with_task(send_bulk_course_email, 'emailed', num_emails - 1, num_emails - 1)
|
||||
|
||||
@@ -239,7 +239,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
for index in range(0, num_emails, 4):
|
||||
Optout.objects.create(user=students[index], course_id=self.course.id)
|
||||
# mark some students as opting out
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([None])
|
||||
self._test_run_with_task(
|
||||
send_bulk_course_email, 'emailed', num_emails, expected_succeeds, skipped=expected_skipped
|
||||
@@ -253,7 +253,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
self._create_students(num_emails - 1)
|
||||
expected_fails = int((num_emails + 3) / 4.0)
|
||||
expected_succeeds = num_emails - expected_fails
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
# have every fourth email fail due to some address failure:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([exception, None, None, None])
|
||||
self._test_run_with_task(
|
||||
@@ -298,7 +298,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
expected_succeeds = num_emails - emails_with_non_ascii_chars + num_of_course_instructors
|
||||
expected_fails = emails_with_non_ascii_chars
|
||||
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([None])
|
||||
self._test_run_with_task(
|
||||
task_class=send_bulk_course_email,
|
||||
@@ -317,7 +317,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
self._create_students(num_emails - 1)
|
||||
expected_fails = 0
|
||||
expected_succeeds = num_emails
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
# Have every other mail attempt fail due to disconnection.
|
||||
get_conn.return_value.send_messages.side_effect = cycle([exception, None])
|
||||
self._test_run_with_task(
|
||||
@@ -338,10 +338,10 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
self._create_students(num_emails - 1)
|
||||
expected_fails = num_emails
|
||||
expected_succeeds = 0
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
# always fail to connect, triggering repeated retries until limit is hit:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([exception])
|
||||
with patch('bulk_email.tasks.update_subtask_status', my_update_subtask_status):
|
||||
with patch('lms.djangoapps.bulk_email.tasks.update_subtask_status', my_update_subtask_status):
|
||||
self._test_run_with_task(
|
||||
send_bulk_course_email,
|
||||
'emailed',
|
||||
@@ -392,7 +392,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
# exceeded"). The maximum recursion depth is 90, so
|
||||
# num_emails * expected_retries < 90.
|
||||
expected_retries = 10
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
# Cycle through N throttling errors followed by a success.
|
||||
get_conn.return_value.send_messages.side_effect = cycle(
|
||||
chain(repeat(exception, expected_retries), [None])
|
||||
@@ -423,7 +423,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
self._create_students(num_emails - 1)
|
||||
expected_fails = num_emails
|
||||
expected_succeeds = 0
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
# always fail to connect, triggering repeated retries until limit is hit:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([exception])
|
||||
self._test_run_with_task(
|
||||
@@ -458,7 +458,7 @@ class TestBulkEmailInstructorTask(InstructorTaskCourseTestCase):
|
||||
# We also send email to the instructor:
|
||||
self._create_students(num_emails - 1)
|
||||
|
||||
with patch('bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
with patch('lms.djangoapps.bulk_email.tasks.get_connection', autospec=True) as get_conn:
|
||||
get_conn.return_value.send_messages.side_effect = cycle([None])
|
||||
self._test_run_with_task(send_bulk_course_email, 'emailed', num_emails, num_emails)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ URLs for bulk_email app
|
||||
from django.conf.urls import url
|
||||
from django.conf import settings
|
||||
|
||||
from bulk_email import views
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(
|
||||
|
||||
@@ -5,7 +5,7 @@ URLs for the Bulk Enrollment API
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from bulk_enroll.views import BulkEnrollView
|
||||
from .views import BulkEnrollView
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^bulk_enroll', BulkEnrollView.as_view(), name='bulk_enroll'),
|
||||
|
||||
@@ -5,19 +5,19 @@ URLs for the CCX Feature.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
import ccx.views
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^ccx_coach$', ccx.views.dashboard, name='ccx_coach_dashboard'),
|
||||
url(r'^create_ccx$', ccx.views.create_ccx, name='create_ccx'),
|
||||
url(r'^save_ccx$', ccx.views.save_ccx, name='save_ccx'),
|
||||
url(r'^ccx_schedule$', ccx.views.ccx_schedule, name='ccx_schedule'),
|
||||
url(r'^ccx-manage-students$', ccx.views.ccx_students_management, name='ccx-manage-students'),
|
||||
url(r'^ccx_coach$', views.dashboard, name='ccx_coach_dashboard'),
|
||||
url(r'^create_ccx$', views.create_ccx, name='create_ccx'),
|
||||
url(r'^save_ccx$', views.save_ccx, name='save_ccx'),
|
||||
url(r'^ccx_schedule$', views.ccx_schedule, name='ccx_schedule'),
|
||||
url(r'^ccx-manage-students$', views.ccx_students_management, name='ccx-manage-students'),
|
||||
|
||||
# Grade book
|
||||
url(r'^ccx_gradebook$', ccx.views.ccx_gradebook, name='ccx_gradebook'),
|
||||
url(r'^ccx_gradebook/(?P<offset>[0-9]+)$', ccx.views.ccx_gradebook, name='ccx_gradebook'),
|
||||
url(r'^ccx_gradebook$', views.ccx_gradebook, name='ccx_gradebook'),
|
||||
url(r'^ccx_gradebook/(?P<offset>[0-9]+)$', views.ccx_gradebook, name='ccx_gradebook'),
|
||||
|
||||
url(r'^ccx_grades.csv$', ccx.views.ccx_grades_csv, name='ccx_grades_csv'),
|
||||
url(r'^ccx_set_grading_policy$', ccx.views.set_grading_policy, name='ccx_set_grading_policy'),
|
||||
url(r'^ccx_grades.csv$', views.ccx_grades_csv, name='ccx_grades_csv'),
|
||||
url(r'^ccx_set_grading_policy$', views.set_grading_policy, name='ccx_set_grading_policy'),
|
||||
]
|
||||
|
||||
@@ -31,7 +31,6 @@ from lms.djangoapps.courseware.fields import UnsignedBigIntAutoField
|
||||
from six import text_type
|
||||
from six.moves import range
|
||||
|
||||
import coursewarehistoryextended
|
||||
from openedx.core.djangolib.markup import HTML
|
||||
|
||||
log = logging.getLogger("edx.courseware")
|
||||
@@ -217,7 +216,8 @@ class BaseStudentModuleHistory(models.Model):
|
||||
history_entries = []
|
||||
|
||||
if settings.FEATURES.get('ENABLE_CSMH_EXTENDED'):
|
||||
history_entries += coursewarehistoryextended.models.StudentModuleHistoryExtended.objects.filter(
|
||||
from lms.djangoapps.coursewarehistoryextended.models import StudentModuleHistoryExtended
|
||||
history_entries += StudentModuleHistoryExtended.objects.filter(
|
||||
# Django will sometimes try to join to courseware_studentmodule
|
||||
# so just do an in query
|
||||
student_module__in=[module.id for module in student_modules]
|
||||
|
||||
5
lms/djangoapps/coursewarehistoryextended/apps.py
Normal file
5
lms/djangoapps/coursewarehistoryextended/apps.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class CoursewareHistoryExtendedConfig(AppConfig):
|
||||
name = u'lms.djangoapps.coursewarehistoryextended'
|
||||
@@ -5,7 +5,7 @@ Urls for sysadmin dashboard feature
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from dashboard import sysadmin
|
||||
from . import sysadmin
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', sysadmin.Users.as_view(), name="sysadmin"),
|
||||
|
||||
@@ -5,7 +5,7 @@ Forum urls for the django_comment_client.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from discussion import views
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'users/(?P<user_id>\w+)/followed$', views.followed_threads, name='followed_threads'),
|
||||
|
||||
@@ -22,7 +22,7 @@ def edxnotes(cls):
|
||||
Returns raw html for the component.
|
||||
"""
|
||||
# Import is placed here to avoid model import at project startup.
|
||||
from edxnotes.helpers import (
|
||||
from .helpers import (
|
||||
generate_uid, get_edxnotes_id_token, get_public_endpoint, get_token_url, is_feature_enabled
|
||||
)
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ from lms.djangoapps.courseware.model_data import FieldDataCache
|
||||
from lms.djangoapps.courseware.module_render import get_module_for_descriptor
|
||||
from lms.djangoapps.courseware.tabs import get_course_tab_list
|
||||
from edxmako.shortcuts import render_to_string
|
||||
from edxnotes import helpers
|
||||
from edxnotes.decorators import edxnotes
|
||||
from edxnotes.exceptions import EdxNotesParseError, EdxNotesServiceUnavailable
|
||||
from edxnotes.plugins import EdxNotesTab
|
||||
from . import helpers
|
||||
from .decorators import edxnotes
|
||||
from .exceptions import EdxNotesParseError, EdxNotesServiceUnavailable
|
||||
from .plugins import EdxNotesTab
|
||||
from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user
|
||||
from openedx.core.djangoapps.oauth_dispatch.tests.factories import ApplicationFactory
|
||||
from openedx.core.djangoapps.user_api.models import RetirementState, UserRetirementStatus
|
||||
@@ -111,10 +111,10 @@ class EdxNotesDecoratorTest(ModuleStoreTestCase):
|
||||
self.problem = TestProblem(self.course, self.user)
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {'ENABLE_EDXNOTES': True})
|
||||
@patch("edxnotes.helpers.get_public_endpoint", autospec=True)
|
||||
@patch("edxnotes.helpers.get_token_url", autospec=True)
|
||||
@patch("edxnotes.helpers.get_edxnotes_id_token", autospec=True)
|
||||
@patch("edxnotes.helpers.generate_uid", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.get_public_endpoint", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.get_token_url", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.get_edxnotes_id_token", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.generate_uid", autospec=True)
|
||||
def test_edxnotes_enabled(self, mock_generate_uid, mock_get_id_token, mock_get_token_url, mock_get_endpoint):
|
||||
"""
|
||||
Tests if get_html is wrapped when feature flag is on and edxnotes are
|
||||
@@ -312,7 +312,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
with patch_edxnotes_api_settings(None):
|
||||
self.assertRaises(ImproperlyConfigured, get_endpoint_function)
|
||||
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_get_notes_correct_data(self, mock_get):
|
||||
"""
|
||||
Tests the result if correct data is received.
|
||||
@@ -405,7 +405,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
helpers.get_notes(self.request, self.course)
|
||||
)
|
||||
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_get_notes_json_error(self, mock_get):
|
||||
"""
|
||||
Tests the result if incorrect json is received.
|
||||
@@ -413,7 +413,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
mock_get.return_value.content = b"Error"
|
||||
self.assertRaises(EdxNotesParseError, helpers.get_notes, self.request, self.course)
|
||||
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_get_notes_empty_collection(self, mock_get):
|
||||
"""
|
||||
Tests the result if an empty response is received.
|
||||
@@ -421,7 +421,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
mock_get.return_value.content = json.dumps({}).encode('utf-8')
|
||||
self.assertRaises(EdxNotesParseError, helpers.get_notes, self.request, self.course)
|
||||
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_search_correct_data(self, mock_get):
|
||||
"""
|
||||
Tests the result if correct data is received.
|
||||
@@ -512,7 +512,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
helpers.get_notes(self.request, self.course)
|
||||
)
|
||||
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_search_json_error(self, mock_get):
|
||||
"""
|
||||
Tests the result if incorrect json is received.
|
||||
@@ -520,7 +520,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
mock_get.return_value.content = b"Error"
|
||||
self.assertRaises(EdxNotesParseError, helpers.get_notes, self.request, self.course)
|
||||
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_search_wrong_data_format(self, mock_get):
|
||||
"""
|
||||
Tests the result if incorrect data structure is received.
|
||||
@@ -528,7 +528,7 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
mock_get.return_value.content = json.dumps({"1": 2}).encode('utf-8')
|
||||
self.assertRaises(EdxNotesParseError, helpers.get_notes, self.request, self.course)
|
||||
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_search_empty_collection(self, mock_get):
|
||||
"""
|
||||
Tests no results.
|
||||
@@ -542,9 +542,9 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
|
||||
@override_settings(EDXNOTES_PUBLIC_API="http://example.com")
|
||||
@override_settings(EDXNOTES_INTERNAL_API="http://example.com")
|
||||
@patch("edxnotes.helpers.anonymous_id_for_user", autospec=True)
|
||||
@patch("edxnotes.helpers.get_edxnotes_id_token", autospec=True)
|
||||
@patch("edxnotes.helpers.requests.post")
|
||||
@patch("lms.djangoapps.edxnotes.helpers.anonymous_id_for_user", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.get_edxnotes_id_token", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.post")
|
||||
def test_delete_all_notes_for_user(self, mock_post, mock_get_id_token, mock_anonymous_id_for_user):
|
||||
"""
|
||||
Test GDPR data deletion for Notes user_id
|
||||
@@ -656,8 +656,8 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
helpers.preprocess_collection(self.user, self.course, initial_collection)
|
||||
)
|
||||
|
||||
@patch("edxnotes.helpers.has_access", autospec=True)
|
||||
@patch("edxnotes.helpers.modulestore", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.has_access", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.modulestore", autospec=True)
|
||||
def test_preprocess_collection_no_unit(self, mock_modulestore, mock_has_access):
|
||||
"""
|
||||
Tests the result if the unit does not exist.
|
||||
@@ -783,9 +783,9 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
|
||||
@override_settings(EDXNOTES_PUBLIC_API="http://example.com")
|
||||
@override_settings(EDXNOTES_INTERNAL_API="http://example.com")
|
||||
@patch("edxnotes.helpers.anonymous_id_for_user", autospec=True)
|
||||
@patch("edxnotes.helpers.get_edxnotes_id_token", autospec=True)
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.anonymous_id_for_user", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.get_edxnotes_id_token", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_send_request_with_text_param(self, mock_get, mock_get_id_token, mock_anonymous_id_for_user):
|
||||
"""
|
||||
Tests that requests are send with correct information.
|
||||
@@ -818,9 +818,9 @@ class EdxNotesHelpersTest(ModuleStoreTestCase):
|
||||
|
||||
@override_settings(EDXNOTES_PUBLIC_API="http://example.com")
|
||||
@override_settings(EDXNOTES_INTERNAL_API="http://example.com")
|
||||
@patch("edxnotes.helpers.anonymous_id_for_user", autospec=True)
|
||||
@patch("edxnotes.helpers.get_edxnotes_id_token", autospec=True)
|
||||
@patch("edxnotes.helpers.requests.get", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.anonymous_id_for_user", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.get_edxnotes_id_token", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.get", autospec=True)
|
||||
def test_send_request_without_text_param(self, mock_get, mock_get_id_token, mock_anonymous_id_for_user):
|
||||
"""
|
||||
Tests that requests are send with correct information.
|
||||
@@ -1018,7 +1018,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@patch("edxnotes.views.get_notes", return_value={'results': []})
|
||||
@patch("lms.djangoapps.edxnotes.views.get_notes", return_value={'results': []})
|
||||
def test_edxnotes_view_is_enabled(self, mock_get_notes):
|
||||
"""
|
||||
Tests that appropriate view is received if EdxNotes feature is enabled.
|
||||
@@ -1029,8 +1029,8 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@patch("edxnotes.views.get_notes", return_value={'results': []})
|
||||
@patch("edxnotes.views.get_course_position", return_value={'display_name': 'Section 1', 'url': 'test_url'})
|
||||
@patch("lms.djangoapps.edxnotes.views.get_notes", return_value={'results': []})
|
||||
@patch("lms.djangoapps.edxnotes.views.get_course_position", return_value={'display_name': 'Section 1', 'url': 'test_url'})
|
||||
def test_edxnotes_html_tags_should_not_be_escaped(self, mock_get_notes, mock_position):
|
||||
"""
|
||||
Tests that explicit html tags rendered correctly.
|
||||
@@ -1051,7 +1051,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@patch("edxnotes.views.get_notes", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.views.get_notes", autospec=True)
|
||||
def test_search_notes_successfully_respond(self, mock_search):
|
||||
"""
|
||||
Tests that search notes successfully respond if EdxNotes feature is enabled.
|
||||
@@ -1071,7 +1071,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@patch("edxnotes.views.get_notes", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.views.get_notes", autospec=True)
|
||||
def test_search_500_service_unavailable(self, mock_search):
|
||||
"""
|
||||
Tests that 500 status code is received if EdxNotes service is unavailable.
|
||||
@@ -1082,7 +1082,7 @@ class EdxNotesViewsTest(ModuleStoreTestCase):
|
||||
self.assertContains(response, "error", status_code=500)
|
||||
|
||||
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_EDXNOTES": True})
|
||||
@patch("edxnotes.views.get_notes", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.views.get_notes", autospec=True)
|
||||
def test_search_notes_exception(self, mock_search):
|
||||
"""
|
||||
Tests that 500 status code is received if invalid data was received from
|
||||
@@ -1199,7 +1199,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
|
||||
headers = {'HTTP_AUTHORIZATION': 'JWT ' + token}
|
||||
return headers
|
||||
|
||||
@patch("edxnotes.helpers.requests.post", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.requests.post", autospec=True)
|
||||
def test_retire_user_success(self, mock_post):
|
||||
"""
|
||||
Tests that 204 response is received on success.
|
||||
@@ -1258,7 +1258,7 @@ class EdxNotesRetireAPITest(ModuleStoreTestCase):
|
||||
)
|
||||
self.assertEqual(response.status_code, 405)
|
||||
|
||||
@patch("edxnotes.helpers.delete_all_notes_for_user", autospec=True)
|
||||
@patch("lms.djangoapps.edxnotes.helpers.delete_all_notes_for_user", autospec=True)
|
||||
def test_retire_user_downstream_unavailable(self, mock_delete_all_notes_for_user):
|
||||
"""
|
||||
Tests that 500 response is received if the downstream (i.e. the EdxNotes IDA) is unavailable.
|
||||
|
||||
@@ -5,7 +5,7 @@ URLs for EdxNotes.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from edxnotes import views
|
||||
from . import views
|
||||
|
||||
# Additionally, we include login URLs for the browseable API.
|
||||
urlpatterns = [
|
||||
|
||||
@@ -16,7 +16,7 @@ from six import text_type
|
||||
|
||||
import third_party_auth
|
||||
from course_modes.models import CourseMode
|
||||
from email_marketing.models import EmailMarketingConfiguration
|
||||
from .models import EmailMarketingConfiguration
|
||||
from lms.djangoapps.email_marketing.tasks import get_email_cookies_via_sailthru, update_user, update_user_email
|
||||
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
|
||||
from openedx.core.djangoapps.user_authn.cookies import CREATE_LOGON_COOKIE
|
||||
|
||||
0
lms/djangoapps/email_marketing/tests/__init__.py
Normal file
0
lms/djangoapps/email_marketing/tests/__init__.py
Normal file
@@ -20,14 +20,14 @@ from sailthru.sailthru_response import SailthruResponse
|
||||
import six
|
||||
from testfixtures import LogCapture
|
||||
|
||||
from email_marketing.models import EmailMarketingConfiguration
|
||||
from email_marketing.signals import (
|
||||
from ..models import EmailMarketingConfiguration
|
||||
from ..signals import (
|
||||
add_email_marketing_cookies,
|
||||
email_marketing_register_user,
|
||||
email_marketing_user_field_changed,
|
||||
update_sailthru
|
||||
)
|
||||
from email_marketing.tasks import (
|
||||
from ..tasks import (
|
||||
_create_user_list,
|
||||
_get_list_from_email_marketing_provider,
|
||||
_get_or_create_user_list,
|
||||
@@ -43,7 +43,7 @@ from util.json_request import JsonResponse
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
LOGGER_NAME = "email_marketing.signals"
|
||||
LOGGER_NAME = "lms.djangoapps.email_marketing.signals"
|
||||
|
||||
TEST_EMAIL = "test@edx.org"
|
||||
|
||||
@@ -94,7 +94,7 @@ class EmailMarketingTests(TestCase):
|
||||
super(EmailMarketingTests, self).setUp()
|
||||
|
||||
@freeze_time(datetime.datetime.now())
|
||||
@patch('email_marketing.signals.crum.get_current_request')
|
||||
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
|
||||
@patch('sailthru.sailthru_client.SailthruClient.api_post')
|
||||
def test_drop_cookie(self, mock_sailthru, mock_get_current_request):
|
||||
"""
|
||||
@@ -176,9 +176,9 @@ class EmailMarketingTests(TestCase):
|
||||
add_email_marketing_cookies(None, response=response, user=self.user)
|
||||
self.assertFalse('sailthru_hid' in response.cookies)
|
||||
|
||||
@patch('email_marketing.tasks.log.error')
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('email_marketing.tasks.SailthruClient.api_get')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_get')
|
||||
def test_add_user(self, mock_sailthru_get, mock_sailthru_post, mock_log_error):
|
||||
"""
|
||||
test async method in tasks that actually updates Sailthru
|
||||
@@ -214,7 +214,7 @@ class EmailMarketingTests(TestCase):
|
||||
)
|
||||
))
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_email_not_sent_to_enterprise_learners(self, mock_sailthru_post):
|
||||
"""
|
||||
tests that welcome email is not sent to the enterprise learner
|
||||
@@ -229,7 +229,7 @@ class EmailMarketingTests(TestCase):
|
||||
)
|
||||
self.assertNotEqual(mock_sailthru_post.call_args[0][0], "send")
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_add_user_list_not_called_on_white_label_domain(self, mock_sailthru_post):
|
||||
"""
|
||||
test user is not added to Sailthru user lists if registered from a whitel labe site
|
||||
@@ -241,8 +241,8 @@ class EmailMarketingTests(TestCase):
|
||||
)
|
||||
self.assertFalse(mock_sailthru_post.called)
|
||||
|
||||
@patch('email_marketing.tasks.log.error')
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_update_user_error_logging(self, mock_sailthru, mock_log_error):
|
||||
"""
|
||||
Ensure that error returned from Sailthru api is logged
|
||||
@@ -270,9 +270,9 @@ class EmailMarketingTests(TestCase):
|
||||
update_user.delay({}, self.user.email, activation=True)
|
||||
self.assertTrue(mock_log_error.called)
|
||||
|
||||
@patch('email_marketing.tasks.update_user.retry')
|
||||
@patch('email_marketing.tasks.log.error')
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.retry')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_update_user_error_retryable(self, mock_sailthru, mock_log_error, mock_retry):
|
||||
"""
|
||||
Ensure that retryable error is retried
|
||||
@@ -282,9 +282,9 @@ class EmailMarketingTests(TestCase):
|
||||
self.assertTrue(mock_log_error.called)
|
||||
self.assertTrue(mock_retry.called)
|
||||
|
||||
@patch('email_marketing.tasks.update_user.retry')
|
||||
@patch('email_marketing.tasks.log.error')
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.retry')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_update_user_error_nonretryable(self, mock_sailthru, mock_log_error, mock_retry):
|
||||
"""
|
||||
Ensure that non-retryable error is not retried
|
||||
@@ -294,8 +294,8 @@ class EmailMarketingTests(TestCase):
|
||||
self.assertTrue(mock_log_error.called)
|
||||
self.assertFalse(mock_retry.called)
|
||||
|
||||
@patch('email_marketing.tasks.log.error')
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_just_return_tasks(self, mock_sailthru, mock_log_error):
|
||||
"""
|
||||
Ensure that disabling Sailthru just returns
|
||||
@@ -312,7 +312,7 @@ class EmailMarketingTests(TestCase):
|
||||
|
||||
update_email_marketing_config(enabled=True)
|
||||
|
||||
@patch('email_marketing.signals.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.signals.log.error')
|
||||
def test_just_return_signals(self, mock_log_error):
|
||||
"""
|
||||
Ensure that disabling Sailthru just returns
|
||||
@@ -335,7 +335,7 @@ class EmailMarketingTests(TestCase):
|
||||
email_marketing_user_field_changed(None, user=anon)
|
||||
self.assertFalse(mock_log_error.called)
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_change_email(self, mock_sailthru):
|
||||
"""
|
||||
test async method in task that changes email in Sailthru
|
||||
@@ -348,7 +348,7 @@ class EmailMarketingTests(TestCase):
|
||||
self.assertEqual(userparms['id'], "old@edx.org")
|
||||
self.assertEqual(userparms['keys']['email'], TEST_EMAIL)
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_or_create_sailthru_list(self, mock_sailthru_client):
|
||||
"""
|
||||
Test the task the create sailthru lists.
|
||||
@@ -382,14 +382,14 @@ class EmailMarketingTests(TestCase):
|
||||
mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []}))
|
||||
self.assertEqual(_get_or_create_user_list(mock_sailthru_client, 'test2_user_list'), None)
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_sailthru_list_map_no_list(self, mock_sailthru_client):
|
||||
"""Test when no list returned from sailthru"""
|
||||
mock_sailthru_client.api_get.return_value = SailthruResponse(JsonResponse({'lists': []}))
|
||||
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
|
||||
mock_sailthru_client.api_get.assert_called_with("list", {})
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_sailthru_list_map_error(self, mock_sailthru_client):
|
||||
"""Test when error occurred while fetching data from sailthru"""
|
||||
mock_sailthru_client.api_get.return_value = SailthruResponse(
|
||||
@@ -397,13 +397,13 @@ class EmailMarketingTests(TestCase):
|
||||
)
|
||||
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_sailthru_list_map_exception(self, mock_sailthru_client):
|
||||
"""Test when exception raised while fetching data from sailthru"""
|
||||
mock_sailthru_client.api_get.side_effect = SailthruClientError
|
||||
self.assertEqual(_get_list_from_email_marketing_provider(mock_sailthru_client), {})
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_get_sailthru_list(self, mock_sailthru_client):
|
||||
"""Test fetch list data from sailthru"""
|
||||
mock_sailthru_client.api_get.return_value = \
|
||||
@@ -414,7 +414,7 @@ class EmailMarketingTests(TestCase):
|
||||
)
|
||||
mock_sailthru_client.api_get.assert_called_with("list", {})
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_create_sailthru_list(self, mock_sailthru_client):
|
||||
"""Test create list in sailthru"""
|
||||
mock_sailthru_client.api_post.return_value = SailthruResponse(JsonResponse({'ok': True}))
|
||||
@@ -425,7 +425,7 @@ class EmailMarketingTests(TestCase):
|
||||
self.assertEqual(listparms['primary'], 0)
|
||||
self.assertEqual(listparms['public_name'], 'test_list_name')
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_create_sailthru_list_error(self, mock_sailthru_client):
|
||||
"""Test error occurrence while creating sailthru list"""
|
||||
mock_sailthru_client.api_post.return_value = SailthruResponse(
|
||||
@@ -433,14 +433,14 @@ class EmailMarketingTests(TestCase):
|
||||
)
|
||||
self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False)
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient')
|
||||
def test_create_sailthru_list_exception(self, mock_sailthru_client):
|
||||
"""Test exception raised while creating sailthru list"""
|
||||
mock_sailthru_client.api_post.side_effect = SailthruClientError
|
||||
self.assertEqual(_create_user_list(mock_sailthru_client, 'test_list_name'), False)
|
||||
|
||||
@patch('email_marketing.tasks.log.error')
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.log.error')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
def test_error_logging(self, mock_sailthru, mock_log_error):
|
||||
"""
|
||||
Ensure that error returned from Sailthru api is logged
|
||||
@@ -453,7 +453,7 @@ class EmailMarketingTests(TestCase):
|
||||
update_user_email.delay(self.user.username, "newemail2@test.com")
|
||||
self.assertTrue(mock_log_error.called)
|
||||
|
||||
@patch('email_marketing.signals.crum.get_current_request')
|
||||
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.delay')
|
||||
def test_register_user(self, mock_update_user, mock_get_current_request):
|
||||
"""
|
||||
@@ -490,7 +490,7 @@ class EmailMarketingTests(TestCase):
|
||||
self.assertEqual(mock_update_user.call_args[0][0]['ui_lang'], 'es-419')
|
||||
|
||||
@patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False})
|
||||
@patch('email_marketing.signals.crum.get_current_request')
|
||||
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.update_user.delay')
|
||||
@ddt.data(('auth_userprofile', 'gender', 'f', True),
|
||||
('auth_user', 'is_active', 1, True),
|
||||
@@ -505,10 +505,10 @@ class EmailMarketingTests(TestCase):
|
||||
email_marketing_user_field_changed(None, self.user, table=table, setting=setting, new_value=value)
|
||||
self.assertEqual(mock_update_user.called, result)
|
||||
|
||||
@patch('email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('email_marketing.signals.third_party_auth.provider.Registry.get_from_pipeline')
|
||||
@patch('email_marketing.signals.third_party_auth.pipeline.get')
|
||||
@patch('email_marketing.signals.crum.get_current_request')
|
||||
@patch('lms.djangoapps.email_marketing.tasks.SailthruClient.api_post')
|
||||
@patch('lms.djangoapps.email_marketing.signals.third_party_auth.provider.Registry.get_from_pipeline')
|
||||
@patch('lms.djangoapps.email_marketing.signals.third_party_auth.pipeline.get')
|
||||
@patch('lms.djangoapps.email_marketing.signals.crum.get_current_request')
|
||||
@ddt.data(True, False)
|
||||
def test_modify_field_with_sso(self, send_welcome_email, mock_get_current_request,
|
||||
mock_pipeline_get, mock_registry_get_from_pipeline, mock_sailthru_post):
|
||||
@@ -632,7 +632,7 @@ class SailthruTests(TestCase):
|
||||
switch.return_value = True
|
||||
white_label_site = Site.objects.create(domain='testwhitelabel.com', name='White Label')
|
||||
site_dict = {'id': white_label_site.id, 'domain': white_label_site.domain, 'name': white_label_site.name}
|
||||
with patch('email_marketing.signals._get_current_site') as mock_site_info:
|
||||
with patch('lms.djangoapps.email_marketing.signals._get_current_site') as mock_site_info:
|
||||
mock_site_info.return_value = site_dict
|
||||
update_sailthru(None, self.user, 'audit', str(self.course_id))
|
||||
self.assertFalse(mock_sailthru_purchase.called)
|
||||
|
||||
8
lms/djangoapps/experiments/apps.py
Normal file
8
lms/djangoapps/experiments/apps.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ExperimentsConfig(AppConfig):
|
||||
"""
|
||||
Application Configuration for experiments.
|
||||
"""
|
||||
name = u'lms.djangoapps.experiments'
|
||||
@@ -40,7 +40,7 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
self.flag = ExperimentWaffleFlag('experiments', 'test', __name__, num_buckets=2, experiment_id=0)
|
||||
self.key = CourseKey.from_string('a/b/c')
|
||||
|
||||
bucket_patch = patch('experiments.flags.stable_bucketing_hash_group', return_value=1)
|
||||
bucket_patch = patch('lms.djangoapps.experiments.flags.stable_bucketing_hash_group', return_value=1)
|
||||
self.addCleanup(bucket_patch.stop)
|
||||
bucket_patch.start()
|
||||
|
||||
@@ -110,7 +110,7 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
|
||||
def test_tracking(self):
|
||||
# Run twice, with same request
|
||||
with patch('experiments.flags.segment') as segment_mock:
|
||||
with patch('lms.djangoapps.experiments.flags.segment') as segment_mock:
|
||||
self.assertEqual(self.get_bucket(track=True), 1)
|
||||
RequestCache.clear_all_namespaces() # we want to force get_bucket to check session, not early exit
|
||||
self.assertEqual(self.get_bucket(track=True), 1)
|
||||
@@ -136,10 +136,10 @@ class ExperimentWaffleFlagTests(SharedModuleStoreTestCase):
|
||||
self.assertEqual(self.get_bucket(active=False), 1) # still returns 1!
|
||||
|
||||
def test_is_enabled(self):
|
||||
with patch('experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=1):
|
||||
with patch('lms.djangoapps.experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=1):
|
||||
self.assertEqual(self.flag.is_enabled(self.key), True)
|
||||
self.assertEqual(self.flag.is_enabled(), True)
|
||||
with patch('experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=0):
|
||||
with patch('lms.djangoapps.experiments.flags.ExperimentWaffleFlag.get_bucket', return_value=0):
|
||||
self.assertEqual(self.flag.is_enabled(self.key), False)
|
||||
self.assertEqual(self.flag.is_enabled(), False)
|
||||
|
||||
@@ -207,7 +207,7 @@ class ExperimentWaffleFlagCourseAwarenessTest(SharedModuleStoreTestCase):
|
||||
|
||||
# Use our custom fake `stable_bucketing_hash_group` implementation.
|
||||
stable_bucket_patcher = patch(
|
||||
'experiments.flags.stable_bucketing_hash_group', self._mock_stable_bucket
|
||||
'lms.djangoapps.experiments.flags.stable_bucketing_hash_group', self._mock_stable_bucket
|
||||
)
|
||||
stable_bucket_patcher.start()
|
||||
self.addCleanup(stable_bucket_patcher.stop)
|
||||
|
||||
@@ -5,7 +5,7 @@ Experimentation URLs
|
||||
|
||||
from django.conf.urls import include, url
|
||||
|
||||
from experiments import routers, views, views_custom
|
||||
from . import routers, views, views_custom
|
||||
|
||||
router = routers.DefaultRouter()
|
||||
router.register(r'data', views.ExperimentDataViewSet, basename='data')
|
||||
|
||||
@@ -349,7 +349,7 @@ class TestEndpointHttpMethods(SharedModuleStoreTestCase, LoginEnrollmentTestCase
|
||||
)
|
||||
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
"""
|
||||
Ensure that users cannot access endpoints they shouldn't be able to.
|
||||
@@ -3378,7 +3378,7 @@ class TestEntranceExamInstructorAPIRegradeTask(SharedModuleStoreTestCase, LoginE
|
||||
self.assertContains(response, message)
|
||||
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class TestInstructorSendEmail(SiteMixin, SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
"""
|
||||
Checks that only instructors have access to email endpoints, and that
|
||||
|
||||
@@ -189,7 +189,7 @@ class InstructorTaskModuleSubmitTest(InstructorTaskModuleTestCase):
|
||||
task_function(self.create_task_request(self.instructor), location, **params)
|
||||
|
||||
|
||||
@patch('bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
@patch('lms.djangoapps.bulk_email.models.html_to_text', Mock(return_value='Mocking CourseEmail.text_message', autospec=True))
|
||||
class InstructorTaskCourseSubmitTest(TestReportMixin, InstructorTaskCourseTestCase):
|
||||
"""Tests API methods that involve the submission of course-based background tasks."""
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class LtiProviderConfig(AppConfig):
|
||||
"""
|
||||
Configuration class for the lti_provider Django application.
|
||||
"""
|
||||
name = 'lti_provider'
|
||||
name = 'lms.djangoapps.lti_provider'
|
||||
verbose_name = "LTI Provider"
|
||||
|
||||
def ready(self):
|
||||
|
||||
@@ -12,8 +12,8 @@ from django.test.client import RequestFactory
|
||||
from mock import MagicMock, PropertyMock, patch
|
||||
from six.moves import range
|
||||
|
||||
import lti_provider.users as users
|
||||
from lti_provider.models import LtiConsumer, LtiUser
|
||||
from .. import users
|
||||
from ..models import LtiConsumer, LtiUser
|
||||
from student.tests.factories import UserFactory
|
||||
|
||||
|
||||
@@ -45,9 +45,9 @@ class UserManagementHelperTest(TestCase):
|
||||
with self.assertRaises(PermissionDenied):
|
||||
users.switch_user(self.request, self.lti_user, self.lti_consumer)
|
||||
|
||||
@patch('lti_provider.users.login')
|
||||
@patch('lms.djangoapps.lti_provider.users.login')
|
||||
def test_authenticate_called(self, _login_mock):
|
||||
with patch('lti_provider.users.authenticate', return_value=self.new_user) as authenticate:
|
||||
with patch('lms.djangoapps.lti_provider.users.authenticate', return_value=self.new_user) as authenticate:
|
||||
users.switch_user(self.request, self.lti_user, self.lti_consumer)
|
||||
authenticate.assert_called_with(
|
||||
username=self.new_user.username,
|
||||
@@ -55,9 +55,9 @@ class UserManagementHelperTest(TestCase):
|
||||
lti_consumer=self.lti_consumer
|
||||
)
|
||||
|
||||
@patch('lti_provider.users.login')
|
||||
@patch('lms.djangoapps.lti_provider.users.login')
|
||||
def test_login_called(self, login_mock):
|
||||
with patch('lti_provider.users.authenticate', return_value=self.new_user):
|
||||
with patch('lms.djangoapps.lti_provider.users.authenticate', return_value=self.new_user):
|
||||
users.switch_user(self.request, self.lti_user, self.lti_consumer)
|
||||
login_mock.assert_called_with(self.request, self.new_user)
|
||||
|
||||
@@ -73,8 +73,8 @@ class UserManagementHelperTest(TestCase):
|
||||
)
|
||||
|
||||
|
||||
@patch('lti_provider.users.switch_user', autospec=True)
|
||||
@patch('lti_provider.users.create_lti_user', autospec=True)
|
||||
@patch('lms.djangoapps.lti_provider.users.switch_user', autospec=True)
|
||||
@patch('lms.djangoapps.lti_provider.users.create_lti_user', autospec=True)
|
||||
class AuthenticateLtiUserTest(TestCase):
|
||||
"""
|
||||
Tests for the authenticate_lti_user function in users.py
|
||||
@@ -111,7 +111,7 @@ class AuthenticateLtiUserTest(TestCase):
|
||||
def test_authentication_with_new_user(self, _create_user, switch_user):
|
||||
lti_user = MagicMock()
|
||||
lti_user.edx_user_id = self.edx_user_id
|
||||
with patch('lti_provider.users.create_lti_user', return_value=lti_user) as create_user:
|
||||
with patch('lms.djangoapps.lti_provider.users.create_lti_user', return_value=lti_user) as create_user:
|
||||
users.authenticate_lti_user(self.request, self.lti_user_id, self.lti_consumer)
|
||||
create_user.assert_called_with(self.lti_user_id, self.lti_consumer)
|
||||
switch_user.assert_called_with(self.request, lti_user, self.lti_consumer)
|
||||
@@ -161,7 +161,7 @@ class CreateLtiUserTest(TestCase):
|
||||
self.assertEqual(User.objects.count(), 1)
|
||||
|
||||
@patch('uuid.uuid4', return_value='random_uuid')
|
||||
@patch('lti_provider.users.generate_random_edx_username', return_value='edx_id')
|
||||
@patch('lms.djangoapps.lti_provider.users.generate_random_edx_username', return_value='edx_id')
|
||||
def test_create_lti_user_creates_correct_user(self, uuid_mock, _username_mock):
|
||||
users.create_lti_user('lti_user_id', self.lti_consumer)
|
||||
self.assertEqual(User.objects.count(), 1)
|
||||
@@ -169,7 +169,7 @@ class CreateLtiUserTest(TestCase):
|
||||
self.assertEqual(user.email, 'edx_id@lti.example.com')
|
||||
uuid_mock.assert_called_with()
|
||||
|
||||
@patch('lti_provider.users.generate_random_edx_username', side_effect=['edx_id', 'new_edx_id'])
|
||||
@patch('lms.djangoapps.lti_provider.users.generate_random_edx_username', side_effect=['edx_id', 'new_edx_id'])
|
||||
def test_unique_username_created(self, username_mock):
|
||||
User(username='edx_id').save()
|
||||
users.create_lti_user('lti_user_id', self.lti_consumer)
|
||||
|
||||
@@ -71,7 +71,7 @@ class LtiTestMixin(object):
|
||||
super(LtiTestMixin, self).setUp()
|
||||
# Always accept the OAuth signature
|
||||
self.mock_verify = MagicMock(return_value=True)
|
||||
patcher = patch('lti_provider.signature_validator.SignatureValidator.verify', self.mock_verify)
|
||||
patcher = patch('lms.djangoapps.lti_provider.signature_validator.SignatureValidator.verify', self.mock_verify)
|
||||
patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
@@ -87,8 +87,8 @@ class LtiLaunchTest(LtiTestMixin, TestCase):
|
||||
"""
|
||||
Tests for the lti_launch view
|
||||
"""
|
||||
@patch('lti_provider.views.render_courseware')
|
||||
@patch('lti_provider.views.authenticate_lti_user')
|
||||
@patch('lms.djangoapps.lti_provider.views.render_courseware')
|
||||
@patch('lms.djangoapps.lti_provider.views.authenticate_lti_user')
|
||||
def test_valid_launch(self, _authenticate, render):
|
||||
"""
|
||||
Verifies that the LTI launch succeeds when passed a valid request.
|
||||
@@ -97,9 +97,9 @@ class LtiLaunchTest(LtiTestMixin, TestCase):
|
||||
views.lti_launch(request, six.text_type(COURSE_KEY), six.text_type(USAGE_KEY))
|
||||
render.assert_called_with(request, USAGE_KEY)
|
||||
|
||||
@patch('lti_provider.views.render_courseware')
|
||||
@patch('lti_provider.views.store_outcome_parameters')
|
||||
@patch('lti_provider.views.authenticate_lti_user')
|
||||
@patch('lms.djangoapps.lti_provider.views.render_courseware')
|
||||
@patch('lms.djangoapps.lti_provider.views.store_outcome_parameters')
|
||||
@patch('lms.djangoapps.lti_provider.views.authenticate_lti_user')
|
||||
def test_valid_launch_with_optional_params(self, _authenticate, store_params, _render):
|
||||
"""
|
||||
Verifies that the LTI launch succeeds when passed a valid request.
|
||||
@@ -112,9 +112,9 @@ class LtiLaunchTest(LtiTestMixin, TestCase):
|
||||
self.consumer
|
||||
)
|
||||
|
||||
@patch('lti_provider.views.render_courseware')
|
||||
@patch('lti_provider.views.store_outcome_parameters')
|
||||
@patch('lti_provider.views.authenticate_lti_user')
|
||||
@patch('lms.djangoapps.lti_provider.views.render_courseware')
|
||||
@patch('lms.djangoapps.lti_provider.views.store_outcome_parameters')
|
||||
@patch('lms.djangoapps.lti_provider.views.authenticate_lti_user')
|
||||
def test_outcome_service_registered(self, _authenticate, store_params, _render):
|
||||
"""
|
||||
Verifies that the LTI launch succeeds when passed a valid request.
|
||||
@@ -168,7 +168,7 @@ class LtiLaunchTest(LtiTestMixin, TestCase):
|
||||
self.assertEqual(response.status_code, 403)
|
||||
self.assertEqual(response.status_code, 403)
|
||||
|
||||
@patch('lti_provider.views.render_courseware')
|
||||
@patch('lms.djangoapps.lti_provider.views.render_courseware')
|
||||
def test_lti_consumer_record_supplemented_with_guid(self, _render):
|
||||
self.mock_verify.return_value = False
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ URLs for the rss_proxy djangoapp.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from rss_proxy.views import proxy
|
||||
from .views import proxy
|
||||
|
||||
app_name = 'rss_proxy'
|
||||
urlpatterns = [
|
||||
|
||||
@@ -9,15 +9,15 @@ from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from mock import patch
|
||||
|
||||
from shoppingcart.models import Order, OrderItem
|
||||
from shoppingcart.processors.CyberSource2 import (
|
||||
from ...models import Order, OrderItem
|
||||
from ..CyberSource2 import (
|
||||
_get_processor_exception_html,
|
||||
get_signed_purchase_params,
|
||||
process_postpay_callback,
|
||||
processor_hash,
|
||||
render_purchase_form_html
|
||||
)
|
||||
from shoppingcart.processors.exceptions import (
|
||||
from ..exceptions import (
|
||||
CCProcessorDataException,
|
||||
CCProcessorSignatureException,
|
||||
CCProcessorWrongAmountException
|
||||
|
||||
@@ -84,7 +84,7 @@ class OrderTest(ModuleStoreTestCase):
|
||||
self.cost = 40
|
||||
|
||||
# Add mock tracker for event testing.
|
||||
patcher = patch('shoppingcart.models.segment')
|
||||
patcher = patch('lms.djangoapps.shoppingcart.models.segment')
|
||||
self.mock_tracker = patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
@@ -299,7 +299,7 @@ class OrderTest(ModuleStoreTestCase):
|
||||
# CertificateItem
|
||||
cart = Order.get_cart_for_user(user=self.user)
|
||||
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
|
||||
with patch('shoppingcart.models.CertificateItem.save', side_effect=DatabaseError):
|
||||
with patch('lms.djangoapps.shoppingcart.models.CertificateItem.save', side_effect=DatabaseError):
|
||||
with self.assertRaises(DatabaseError):
|
||||
cart.purchase()
|
||||
# verify that we rolled back the entire transaction
|
||||
@@ -315,15 +315,15 @@ class OrderTest(ModuleStoreTestCase):
|
||||
cart.purchase()
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
|
||||
@patch('shoppingcart.models.log.error')
|
||||
@patch('lms.djangoapps.shoppingcart.models.log.error')
|
||||
def test_purchase_item_email_smtp_failure(self, error_logger):
|
||||
cart = Order.get_cart_for_user(user=self.user)
|
||||
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
|
||||
with patch('shoppingcart.models.EmailMessage.send', side_effect=smtplib.SMTPException):
|
||||
with patch('lms.djangoapps.shoppingcart.models.EmailMessage.send', side_effect=smtplib.SMTPException):
|
||||
cart.purchase()
|
||||
self.assertTrue(error_logger.called)
|
||||
|
||||
@patch('shoppingcart.models.log.error')
|
||||
@patch('lms.djangoapps.shoppingcart.models.log.error')
|
||||
def test_purchase_item_email_boto_failure(self, error_logger):
|
||||
cart = Order.get_cart_for_user(user=self.user)
|
||||
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
|
||||
@@ -348,7 +348,7 @@ class OrderTest(ModuleStoreTestCase):
|
||||
cardtype='001',
|
||||
)
|
||||
|
||||
@patch('shoppingcart.models.render_to_string')
|
||||
@patch('lms.djangoapps.shoppingcart.models.render_to_string')
|
||||
@patch.dict(settings.FEATURES, {'STORE_BILLING_INFO': True})
|
||||
def test_billing_info_storage_on(self, render):
|
||||
cart = Order.get_cart_for_user(self.user)
|
||||
@@ -366,7 +366,7 @@ class OrderTest(ModuleStoreTestCase):
|
||||
((_, context), _) = render.call_args
|
||||
self.assertTrue(context['has_billing_info'])
|
||||
|
||||
@patch('shoppingcart.models.render_to_string')
|
||||
@patch('lms.djangoapps.shoppingcart.models.render_to_string')
|
||||
@patch.dict(settings.FEATURES, {'STORE_BILLING_INFO': False})
|
||||
def test_billing_info_storage_off(self, render):
|
||||
cart = Order.get_cart_for_user(self.user)
|
||||
@@ -517,7 +517,7 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
self.mock_tracker = patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
analytics_patcher = patch('shoppingcart.models.segment')
|
||||
analytics_patcher = patch('lms.djangoapps.shoppingcart.models.segment')
|
||||
self.mock_analytics_tracker = analytics_patcher.start()
|
||||
self.addCleanup(analytics_patcher.stop)
|
||||
|
||||
@@ -657,7 +657,7 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
|
||||
mail.outbox = []
|
||||
cutoff_date.return_value = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
|
||||
with patch('shoppingcart.models.log.error') as mock_error_logger:
|
||||
with patch('lms.djangoapps.shoppingcart.models.log.error') as mock_error_logger:
|
||||
CourseEnrollment.unenroll(self.user, course_key)
|
||||
self.assertFalse(mock_error_logger.called)
|
||||
self.assertEqual(len(mail.outbox), 1)
|
||||
@@ -666,7 +666,7 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
self.assertIn('has requested a refund on Order', mail.outbox[0].body)
|
||||
|
||||
@patch('student.models.CourseEnrollment.refund_cutoff_date')
|
||||
@patch('shoppingcart.models.log.error')
|
||||
@patch('lms.djangoapps.shoppingcart.models.log.error')
|
||||
def test_refund_cert_callback_before_expiration_email_error(self, error_logger, cutoff_date):
|
||||
# If there's an error sending an email to billing, we need to log this error
|
||||
many_days = datetime.timedelta(days=60)
|
||||
@@ -687,7 +687,7 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
cart.purchase()
|
||||
|
||||
cutoff_date.return_value = datetime.datetime.now(pytz.UTC) + datetime.timedelta(days=1)
|
||||
with patch('shoppingcart.models.send_mail', side_effect=smtplib.SMTPException):
|
||||
with patch('lms.djangoapps.shoppingcart.models.send_mail', side_effect=smtplib.SMTPException):
|
||||
CourseEnrollment.unenroll(self.user, course_key)
|
||||
self.assertTrue(error_logger.call_args[0][0].startswith('Failed sending email'))
|
||||
|
||||
|
||||
@@ -34,8 +34,8 @@ from course_modes.tests.factories import CourseModeFactory
|
||||
from lms.djangoapps.courseware.tests.factories import InstructorFactory
|
||||
from edxmako.shortcuts import render_to_response
|
||||
from openedx.core.djangoapps.embargo.test_utils import restrict_course
|
||||
from shoppingcart.admin import SoftDeleteCouponAdmin
|
||||
from shoppingcart.models import (
|
||||
from ..admin import SoftDeleteCouponAdmin
|
||||
from ..models import (
|
||||
CertificateItem,
|
||||
Coupon,
|
||||
CouponRedemption,
|
||||
@@ -46,10 +46,10 @@ from shoppingcart.models import (
|
||||
PaidCourseRegistration,
|
||||
RegistrationCodeRedemption
|
||||
)
|
||||
from shoppingcart.processors import render_purchase_form_html
|
||||
from shoppingcart.processors.CyberSource2 import sign
|
||||
from shoppingcart.tests.payment_fake import PaymentFakeView
|
||||
from shoppingcart.views import _can_download_report, _get_date_from_str, initialize_report
|
||||
from ..processors import render_purchase_form_html
|
||||
from ..processors.CyberSource2 import sign
|
||||
from ..tests.payment_fake import PaymentFakeView
|
||||
from ..views import _can_download_report, _get_date_from_str, initialize_report
|
||||
from student.models import CourseEnrollment
|
||||
from student.roles import CourseSalesAdminRole
|
||||
from student.tests.factories import AdminFactory, UserFactory
|
||||
@@ -204,7 +204,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
resp = self.client.post(reverse('add_course_to_cart', args=[text_type(self.course_key)]))
|
||||
self.assertEqual(resp.status_code, 403)
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_billing_details(self):
|
||||
billing_url = reverse('billing_details')
|
||||
self.login_user()
|
||||
@@ -235,7 +235,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
resp = self.client.post(billing_url, data)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
@override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs'])
|
||||
def test_billing_details_with_override_currency_settings(self):
|
||||
billing_url = reverse('billing_details')
|
||||
@@ -668,7 +668,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
current_enrollment, __ = CourseEnrollment.enrollment_mode_for_user(self.user, self.course_key)
|
||||
self.assertEqual('verified', current_enrollment)
|
||||
|
||||
@patch('shoppingcart.views.log.debug')
|
||||
@patch('lms.djangoapps.shoppingcart.views.log.debug')
|
||||
def test_non_existing_coupon_redemption_on_removing_item(self, debug_log):
|
||||
|
||||
reg_item = self.add_course_to_user_cart(self.course_key)
|
||||
@@ -682,7 +682,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(self.cart.orderitem_set.count(), 0)
|
||||
|
||||
@patch('shoppingcart.views.log.info')
|
||||
@patch('lms.djangoapps.shoppingcart.views.log.info')
|
||||
def test_existing_coupon_redemption_on_removing_item(self, info_log):
|
||||
|
||||
self.add_coupon(self.course_key, True, self.coupon_code)
|
||||
@@ -703,7 +703,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
str(reg_item.id)
|
||||
)
|
||||
|
||||
@patch('shoppingcart.views.log.info')
|
||||
@patch('lms.djangoapps.shoppingcart.views.log.info')
|
||||
def test_reset_redemption_for_coupon(self, info_log):
|
||||
|
||||
self.add_coupon(self.course_key, True, self.coupon_code)
|
||||
@@ -721,7 +721,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
reg_item.id
|
||||
)
|
||||
|
||||
@patch('shoppingcart.views.log.info')
|
||||
@patch('lms.djangoapps.shoppingcart.views.log.info')
|
||||
def test_coupon_discount_for_multiple_courses_in_cart(self, info_log):
|
||||
|
||||
reg_item = self.add_course_to_user_cart(self.course_key)
|
||||
@@ -756,7 +756,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
str(reg_item.id)
|
||||
)
|
||||
|
||||
@patch('shoppingcart.views.log.info')
|
||||
@patch('lms.djangoapps.shoppingcart.views.log.info')
|
||||
def test_delete_certificate_item(self, info_log):
|
||||
|
||||
self.add_course_to_user_cart(self.course_key)
|
||||
@@ -772,7 +772,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertEqual(self.cart.orderitem_set.count(), 1)
|
||||
info_log.assert_called_with(u"order item %s removed for user %s", str(cert_item.id), self.user)
|
||||
|
||||
@patch('shoppingcart.views.log.info')
|
||||
@patch('lms.djangoapps.shoppingcart.views.log.info')
|
||||
def test_remove_coupon_redemption_on_clear_cart(self, info_log):
|
||||
|
||||
reg_item = self.add_course_to_user_cart(self.course_key)
|
||||
@@ -815,8 +815,8 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertTrue(PaidCourseRegistration.contained_in_order(self.cart, self.course_key))
|
||||
|
||||
@patch('shoppingcart.views.render_purchase_form_html', form_mock)
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_purchase_form_html', form_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_show_cart(self):
|
||||
self.login_user()
|
||||
reg_item = PaidCourseRegistration.add_to_order(
|
||||
@@ -848,8 +848,8 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertEqual(context['currency'], 'usd')
|
||||
self.assertEqual(context['currency_symbol'], '$')
|
||||
|
||||
@patch('shoppingcart.views.render_purchase_form_html', form_mock)
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_purchase_form_html', form_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
@override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs'])
|
||||
def test_show_cart_with_override_currency_settings(self):
|
||||
self.login_user()
|
||||
@@ -876,7 +876,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
self.assertEqual(self.cart.orderitem_set.count(), 0)
|
||||
|
||||
@patch('shoppingcart.views.log.exception')
|
||||
@patch('lms.djangoapps.shoppingcart.views.log.exception')
|
||||
def test_remove_item(self, exception_log):
|
||||
self.login_user()
|
||||
reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
|
||||
@@ -906,7 +906,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
'-1'
|
||||
)
|
||||
|
||||
@patch('shoppingcart.views.process_postpay_callback', postpay_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.process_postpay_callback', postpay_mock)
|
||||
def test_postpay_callback_success(self):
|
||||
postpay_mock.return_value = {'success': True, 'order': self.cart}
|
||||
self.login_user()
|
||||
@@ -915,8 +915,8 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertEqual(urlparse(resp.__getitem__('location')).path,
|
||||
reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))
|
||||
|
||||
@patch('shoppingcart.views.process_postpay_callback', postpay_mock)
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.process_postpay_callback', postpay_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_postpay_callback_failure(self):
|
||||
postpay_mock.return_value = {'success': False, 'order': self.cart, 'error_html': 'ERROR_TEST!!!'}
|
||||
self.login_user()
|
||||
@@ -977,7 +977,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
resp = self.client.get(url)
|
||||
self.assert_no_xss(resp, '<script>alert("XSS")</script>')
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_reg_code_xss(self):
|
||||
self.add_reg_code(self.xss_course_key)
|
||||
|
||||
@@ -1099,7 +1099,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
total_amount = PaidCourseRegistration.get_total_amount_of_purchased_item(self.course_key)
|
||||
self.assertEqual(total_amount, 76)
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_show_receipt_success_with_valid_coupon_code(self):
|
||||
self.add_course_to_user_cart(self.course_key)
|
||||
self.add_coupon(self.course_key, True, self.coupon_code)
|
||||
@@ -1112,7 +1112,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertContains(resp, 'FirstNameTesting123')
|
||||
self.assertContains(resp, str(self.get_discount(self.cost)))
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_reg_code_and_course_registration_scenario(self):
|
||||
self.add_reg_code(self.course_key)
|
||||
|
||||
@@ -1133,7 +1133,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
response = self.client.post(redeem_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_reg_code_with_multiple_courses_and_checkout_scenario(self):
|
||||
self.add_reg_code(self.course_key)
|
||||
|
||||
@@ -1182,7 +1182,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertIsNotNone(item2.course_enrollment)
|
||||
self.assertEqual(item2.course_enrollment.course_id, self.testing_course.id)
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_show_receipt_success_with_valid_reg_code(self):
|
||||
self.add_course_to_user_cart(self.course_key)
|
||||
self.add_reg_code(self.course_key)
|
||||
@@ -1194,7 +1194,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
resp = self.client.get(reverse('shoppingcart.views.show_receipt', args=[self.cart.id]))
|
||||
self.assertContains(resp, '0.00')
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_show_receipt_success(self):
|
||||
reg_item = PaidCourseRegistration.add_to_order(
|
||||
self.cart,
|
||||
@@ -1220,7 +1220,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertEqual(context['currency'], 'usd')
|
||||
|
||||
@override_settings(PAID_COURSE_REGISTRATION_CURRENCY=['PKR', 'Rs'])
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_show_receipt_success_with_override_currency_settings(self):
|
||||
reg_item = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
|
||||
cert_item = CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'honor')
|
||||
@@ -1239,7 +1239,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertEqual(context['currency_symbol'], 'Rs')
|
||||
self.assertEqual(context['currency'], 'PKR')
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_show_receipt_success_with_upgrade(self):
|
||||
|
||||
reg_item = PaidCourseRegistration.add_to_order(
|
||||
@@ -1268,7 +1268,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertIn(cert_item, context['shoppingcart_items'][1])
|
||||
self.assertFalse(context['any_refunds'])
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_show_receipt_success_refund(self):
|
||||
reg_item = PaidCourseRegistration.add_to_order(
|
||||
self.cart,
|
||||
@@ -1291,7 +1291,7 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
|
||||
self.assertIn(cert_item, context['shoppingcart_items'][1])
|
||||
self.assertTrue(context['any_refunds'])
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_show_receipt_success_custom_receipt_page(self):
|
||||
cert_item = CertificateItem.add_to_order(self.cart, self.course_key, self.cost, 'honor')
|
||||
self.cart.purchase()
|
||||
@@ -1432,7 +1432,7 @@ class ReceiptRedirectTest(SharedModuleStoreTestCase):
|
||||
self.cart.start_purchase()
|
||||
|
||||
# Simulate hitting the post-pay callback
|
||||
with patch('shoppingcart.views.process_postpay_callback') as mock_process:
|
||||
with patch('lms.djangoapps.shoppingcart.views.process_postpay_callback') as mock_process:
|
||||
mock_process.return_value = {'success': True, 'order': self.cart}
|
||||
url = reverse('shoppingcart.views.postpay_callback')
|
||||
resp = self.client.post(url, follow=True)
|
||||
@@ -1510,7 +1510,7 @@ class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase):
|
||||
"""
|
||||
self.client.login(username=self.user.username, password="password")
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_to_check_that_cart_item_enrollment_is_closed(self):
|
||||
self.login_user()
|
||||
reg_item1 = PaidCourseRegistration.add_to_order(self.cart, self.course_key)
|
||||
@@ -1911,7 +1911,7 @@ class CSVReportViewsTest(SharedModuleStoreTestCase):
|
||||
response = self.client.put(reverse('payment_csv_report'))
|
||||
self.assertEqual(response.status_code, 400)
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_report_csv_get(self):
|
||||
self.login_user()
|
||||
self.add_to_download_group(self.user)
|
||||
@@ -1923,7 +1923,7 @@ class CSVReportViewsTest(SharedModuleStoreTestCase):
|
||||
self.assertFalse(context['date_fmt_error'])
|
||||
self.assertContains(response, "Download CSV Reports")
|
||||
|
||||
@patch('shoppingcart.views.render_to_response', render_mock)
|
||||
@patch('lms.djangoapps.shoppingcart.views.render_to_response', render_mock)
|
||||
def test_report_csv_bad_date(self):
|
||||
self.login_user()
|
||||
self.add_to_download_group(self.user)
|
||||
|
||||
@@ -6,7 +6,7 @@ Defines the shoppingcart URLs
|
||||
from django.conf import settings
|
||||
from django.conf.urls import url
|
||||
|
||||
from shoppingcart import views
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
# Both the ~accept and ~reject callback pages are handled here
|
||||
|
||||
@@ -430,7 +430,7 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
|
||||
kwargs={'username_or_email': getattr(self.student, search_string_type)}
|
||||
)
|
||||
|
||||
with patch('support.views.enrollments.get_credit_provider_attribute_values') as mock_method:
|
||||
with patch('lms.djangoapps.support.views.enrollments.get_credit_provider_attribute_values') as mock_method:
|
||||
credit_provider = (
|
||||
[u'Arizona State University'], 'You are now eligible for credit from Arizona State University'
|
||||
)
|
||||
@@ -469,7 +469,7 @@ class SupportViewLinkProgramEnrollmentsTests(SupportViewTestCase):
|
||||
Tests for the link_program_enrollments support view.
|
||||
"""
|
||||
patch_render = patch(
|
||||
'support.views.program_enrollments.render_to_response',
|
||||
'lms.djangoapps.support.views.program_enrollments.render_to_response',
|
||||
return_value=HttpResponse(),
|
||||
autospec=True,
|
||||
)
|
||||
@@ -537,7 +537,7 @@ class SupportViewLinkProgramEnrollmentsTests(SupportViewTestCase):
|
||||
'0001,learner-01,apple,orange\n0002,learner-02,purple', # extra fields
|
||||
'\t0001 , \t learner-01 \n 0002 , learner-02 ', # whitespace
|
||||
)
|
||||
@patch('support.views.program_enrollments.link_program_enrollments')
|
||||
@patch('lms.djangoapps.support.views.program_enrollments.link_program_enrollments')
|
||||
def test_text(self, text, mocked_link):
|
||||
self.client.post(self.url, data={
|
||||
'program_uuid': self.program_uuid,
|
||||
@@ -638,7 +638,7 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
View tests for Program Enrollments Inspector
|
||||
"""
|
||||
patch_render = patch(
|
||||
'support.views.program_enrollments.render_to_response',
|
||||
'lms.djangoapps.support.views.program_enrollments.render_to_response',
|
||||
return_value=HttpResponse(),
|
||||
autospec=True,
|
||||
)
|
||||
|
||||
@@ -5,15 +5,15 @@ URLs for the student support app.
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from lms.djangoapps.support.views.contact_us import ContactUsView
|
||||
from support.views.certificate import CertificatesSupportView
|
||||
from support.views.course_entitlements import EntitlementSupportView
|
||||
from support.views.enrollments import EnrollmentSupportListView, EnrollmentSupportView
|
||||
from support.views.feature_based_enrollments import FeatureBasedEnrollmentsSupportView
|
||||
from support.views.index import index
|
||||
from support.views.manage_user import ManageUserDetailView, ManageUserSupportView
|
||||
from support.views.program_enrollments import LinkProgramEnrollmentSupportView, ProgramEnrollmentsInspectorView
|
||||
from support.views.sso_records import SsoView
|
||||
from .views.contact_us import ContactUsView
|
||||
from .views.certificate import CertificatesSupportView
|
||||
from .views.course_entitlements import EntitlementSupportView
|
||||
from .views.enrollments import EnrollmentSupportListView, EnrollmentSupportView
|
||||
from .views.feature_based_enrollments import FeatureBasedEnrollmentsSupportView
|
||||
from .views.index import index
|
||||
from .views.manage_user import ManageUserDetailView, ManageUserSupportView
|
||||
from .views.program_enrollments import LinkProgramEnrollmentSupportView, ProgramEnrollmentsInspectorView
|
||||
from .views.sso_records import SsoView
|
||||
|
||||
COURSE_ENTITLEMENTS_VIEW = EntitlementSupportView.as_view()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ class SoftwareSecureFakeViewTest(UrlResetMixin, TestCase):
|
||||
Base class to test the fake software secure view.
|
||||
"""
|
||||
|
||||
URLCONF_MODULES = ['verify_student.urls']
|
||||
URLCONF_MODULES = ['lms.djangoapps.verify_student.urls']
|
||||
|
||||
def setUp(self, **kwargs):
|
||||
enable_software_secure_fake = kwargs.get('enable_software_secure_fake', False)
|
||||
|
||||
@@ -21,6 +21,7 @@ from django.utils.translation import ugettext_lazy
|
||||
from path import Path as path
|
||||
|
||||
from openedx.core.release import RELEASE_LINE
|
||||
from xmodule.modulestore.modulestore_settings import update_module_store_settings
|
||||
|
||||
CONFIG_ROOT = path(__file__).abspath().dirname()
|
||||
TEST_ROOT = CONFIG_ROOT.dirname().dirname() / "test_root"
|
||||
|
||||
@@ -52,8 +52,6 @@ from openedx.core.djangoapps.theming.helpers_dirs import (
|
||||
)
|
||||
from openedx.core.lib.derived import derived, derived_collection_entry
|
||||
from openedx.core.release import doc_version
|
||||
from xmodule.modulestore.modulestore_settings import update_module_store_settings
|
||||
from xmodule.modulestore.edit_info import EditInfoMixin
|
||||
from lms.djangoapps.lms_xblock.mixin import LmsBlockMixin
|
||||
|
||||
################################### FEATURES ###################################
|
||||
@@ -724,7 +722,7 @@ DATA_DIR = COURSES_ROOT
|
||||
|
||||
# TODO: Remove the rest of the sys.path modification here and in cms/envs/common.py
|
||||
sys.path.append(REPO_ROOT)
|
||||
sys.path.append(PROJECT_ROOT / 'djangoapps')
|
||||
sys.path.append(REPO_ROOT / 'sys_path_hacks' / 'lms')
|
||||
sys.path.append(COMMON_ROOT / 'djangoapps')
|
||||
|
||||
# For Node.js
|
||||
@@ -1169,9 +1167,12 @@ COURSE_LISTINGS = {}
|
||||
############# XBlock Configuration ##########
|
||||
|
||||
# Import after sys.path fixup
|
||||
# pylint: disable=wrong-import-position
|
||||
from xmodule.modulestore.edit_info import EditInfoMixin
|
||||
from xmodule.modulestore.inheritance import InheritanceMixin
|
||||
from xmodule.modulestore import prefer_xmodules
|
||||
from xmodule.x_module import XModuleMixin
|
||||
# pylint: enable=wrong-import-position
|
||||
|
||||
# These are the Mixins that should be added to every XBlock.
|
||||
# This should be moved into an XBlock Runtime/Application object
|
||||
@@ -2483,26 +2484,26 @@ INSTALLED_APPS = [
|
||||
|
||||
# Our courseware
|
||||
'lms.djangoapps.courseware',
|
||||
'coursewarehistoryextended',
|
||||
'lms.djangoapps.coursewarehistoryextended',
|
||||
'student.apps.StudentConfig',
|
||||
|
||||
'static_template_view',
|
||||
'staticbook',
|
||||
'lms.djangoapps.static_template_view',
|
||||
'lms.djangoapps.staticbook',
|
||||
'track',
|
||||
'eventtracking.django.apps.EventTrackingConfig',
|
||||
'util',
|
||||
'lms.djangoapps.certificates.apps.CertificatesConfig',
|
||||
'dashboard',
|
||||
'lms.djangoapps.dashboard',
|
||||
'lms.djangoapps.instructor_task',
|
||||
'openedx.core.djangoapps.course_groups',
|
||||
'bulk_email',
|
||||
'branding',
|
||||
'lms.djangoapps.bulk_email',
|
||||
'lms.djangoapps.branding',
|
||||
|
||||
# New (Blockstore-based) XBlock runtime
|
||||
'openedx.core.djangoapps.xblock.apps.LmsXBlockAppConfig',
|
||||
|
||||
# Student support tools
|
||||
'support',
|
||||
'lms.djangoapps.support',
|
||||
|
||||
# django-oauth-toolkit
|
||||
'oauth2_provider',
|
||||
@@ -2518,7 +2519,7 @@ INSTALLED_APPS = [
|
||||
# For the wiki
|
||||
'wiki', # The new django-wiki from benjaoming
|
||||
'django_notify',
|
||||
'course_wiki', # Our customizations
|
||||
'lms.djangoapps.course_wiki', # Our customizations
|
||||
'mptt',
|
||||
'sekizai',
|
||||
#'wiki.plugins.attachments',
|
||||
@@ -2527,18 +2528,18 @@ INSTALLED_APPS = [
|
||||
# got tangled up during the Django 1.8 migration, so we are disabling it.
|
||||
# See TNL-3783 for details.
|
||||
#'wiki.plugins.notifications',
|
||||
'course_wiki.plugins.markdownedx',
|
||||
'lms.djangoapps.course_wiki.plugins.markdownedx',
|
||||
|
||||
# For testing
|
||||
'django.contrib.admin', # only used in DEBUG mode
|
||||
'debug',
|
||||
'lms.djangoapps.debug',
|
||||
'openedx.core.djangoapps.util.apps.UtilConfig',
|
||||
|
||||
# Discussion forums
|
||||
'openedx.core.djangoapps.django_comment_common',
|
||||
|
||||
# Notes
|
||||
'edxnotes',
|
||||
'lms.djangoapps.edxnotes',
|
||||
|
||||
# Splash screen
|
||||
'splash',
|
||||
@@ -2549,7 +2550,7 @@ INSTALLED_APPS = [
|
||||
'openedx.core.djangoapps.user_api',
|
||||
|
||||
# Shopping cart
|
||||
'shoppingcart',
|
||||
'lms.djangoapps.shoppingcart',
|
||||
|
||||
# Different Course Modes
|
||||
'course_modes.apps.CourseModesConfig',
|
||||
@@ -2561,7 +2562,7 @@ INSTALLED_APPS = [
|
||||
'entitlements.apps.EntitlementsConfig',
|
||||
|
||||
# Bulk Enrollment API
|
||||
'bulk_enroll',
|
||||
'lms.djangoapps.bulk_enroll',
|
||||
|
||||
# Student Identity Verification
|
||||
'lms.djangoapps.verify_student.apps.VerifyStudentConfig',
|
||||
@@ -2570,7 +2571,7 @@ INSTALLED_APPS = [
|
||||
'openedx.core.djangoapps.dark_lang',
|
||||
|
||||
# RSS Proxy
|
||||
'rss_proxy',
|
||||
'lms.djangoapps.rss_proxy',
|
||||
|
||||
# Country embargo support
|
||||
'openedx.core.djangoapps.embargo',
|
||||
@@ -2649,7 +2650,7 @@ INSTALLED_APPS = [
|
||||
'learner_dashboard',
|
||||
|
||||
# Needed whether or not enabled, due to migrations
|
||||
'badges.apps.BadgesConfig',
|
||||
'lms.djangoapps.badges.apps.BadgesConfig',
|
||||
|
||||
# Enables default site and redirects
|
||||
'django_sites_extensions',
|
||||
@@ -2690,7 +2691,7 @@ INSTALLED_APPS = [
|
||||
'openedx.features.content_type_gating',
|
||||
'openedx.features.discounts',
|
||||
|
||||
'experiments',
|
||||
'lms.djangoapps.experiments',
|
||||
|
||||
# DRF filters
|
||||
'django_filters',
|
||||
|
||||
@@ -771,8 +771,8 @@ CREDIT_PROVIDER_SECRET_KEYS = AUTH_TOKENS.get("CREDIT_PROVIDER_SECRET_KEYS", {})
|
||||
|
||||
##################### LTI Provider #####################
|
||||
if FEATURES.get('ENABLE_LTI_PROVIDER'):
|
||||
INSTALLED_APPS.append('lti_provider.apps.LtiProviderConfig')
|
||||
AUTHENTICATION_BACKENDS.append('lti_provider.users.LtiBackend')
|
||||
INSTALLED_APPS.append('lms.djangoapps.lti_provider.apps.LtiProviderConfig')
|
||||
AUTHENTICATION_BACKENDS.append('lms.djangoapps.lti_provider.users.LtiBackend')
|
||||
|
||||
LTI_USER_EMAIL_DOMAIN = ENV_TOKENS.get('LTI_USER_EMAIL_DOMAIN', 'lti.example.com')
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ from six.moves import range
|
||||
from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType
|
||||
from openedx.core.lib.derived import derive_settings
|
||||
from openedx.core.lib.tempdir import mkdtemp_clean
|
||||
from xmodule.modulestore.modulestore_settings import update_module_store_settings
|
||||
|
||||
from .common import *
|
||||
|
||||
|
||||
16
lms/urls.py
16
lms/urls.py
@@ -13,8 +13,8 @@ from edx_api_doc_tools import make_docs_urls
|
||||
from edx_django_utils.plugins import get_plugin_url_patterns
|
||||
from ratelimitbackend import admin
|
||||
|
||||
from branding import views as branding_views
|
||||
from debug import views as debug_views
|
||||
from lms.djangoapps.branding import views as branding_views
|
||||
from lms.djangoapps.debug import views as debug_views
|
||||
from lms.djangoapps.certificates import views as certificates_views
|
||||
from lms.djangoapps.courseware.masquerade import MasqueradeView
|
||||
from lms.djangoapps.courseware.module_render import (
|
||||
@@ -31,6 +31,8 @@ from lms.djangoapps.discussion.config.settings import is_forum_daily_digest_enab
|
||||
from lms.djangoapps.discussion.notification_prefs import views as notification_prefs_views
|
||||
from lms.djangoapps.instructor.views import instructor_dashboard as instructor_dashboard_views
|
||||
from lms.djangoapps.instructor_task import views as instructor_task_views
|
||||
from lms.djangoapps.staticbook import views as staticbook_views
|
||||
from lms.djangoapps.static_template_view import views as static_template_view_views
|
||||
from openedx.core.apidocs import api_info
|
||||
from openedx.core.djangoapps.auth_exchange.views import LoginWithAccessTokenView
|
||||
from openedx.core.djangoapps.catalog.models import CatalogIntegration
|
||||
@@ -49,8 +51,6 @@ from openedx.core.djangoapps.site_configuration import helpers as configuration_
|
||||
from openedx.core.djangoapps.user_authn.views.login import redirect_to_lms_login
|
||||
from openedx.core.djangoapps.verified_track_content import views as verified_track_content_views
|
||||
from openedx.features.enterprise_support.api import enterprise_enabled
|
||||
from static_template_view import views as static_template_view_views
|
||||
from staticbook import views as staticbook_views
|
||||
from student import views as student_views
|
||||
from util import views as util_views
|
||||
|
||||
@@ -159,7 +159,7 @@ urlpatterns = [
|
||||
url(r'^api/course_modes/', include(('course_modes.rest_api.urls', 'common.djangoapps.course_mods'),
|
||||
namespace='course_modes_api')),
|
||||
|
||||
url(r'^verify_student/', include('verify_student.urls')),
|
||||
url(r'^verify_student/', include('lms.djangoapps.verify_student.urls')),
|
||||
|
||||
# URLs for managing dark launches of languages
|
||||
url(r'^update_lang/', include(('openedx.core.djangoapps.dark_lang.urls', 'openedx.core.djangoapps.dark_lang'),
|
||||
@@ -212,7 +212,7 @@ urlpatterns += [
|
||||
# the custom tab catch-all)
|
||||
if settings.WIKI_ENABLED:
|
||||
from wiki.urls import get_pattern as wiki_pattern
|
||||
from course_wiki import views as course_wiki_views
|
||||
from lms.djangoapps.course_wiki import views as course_wiki_views
|
||||
from django_notify.urls import get_pattern as notify_pattern
|
||||
|
||||
wiki_url_patterns, wiki_app_name = wiki_pattern()
|
||||
@@ -854,7 +854,7 @@ if settings.FEATURES.get('ENABLE_OAUTH2_PROVIDER'):
|
||||
|
||||
# Certificates
|
||||
urlpatterns += [
|
||||
url(r'^certificates/', include('certificates.urls')),
|
||||
url(r'^certificates/', include('lms.djangoapps.certificates.urls')),
|
||||
|
||||
# Backwards compatibility with XQueue, which uses URLs that are not prefixed with /certificates/
|
||||
url(r'^update_certificate$', certificates_views.update_certificate, name='update_certificate'),
|
||||
@@ -885,7 +885,7 @@ if settings.FEATURES.get('CUSTOM_COURSES_EDX'):
|
||||
# Access to courseware as an LTI provider
|
||||
if settings.FEATURES.get('ENABLE_LTI_PROVIDER'):
|
||||
urlpatterns += [
|
||||
url(r'^lti_provider/', include('lti_provider.urls')),
|
||||
url(r'^lti_provider/', include('lms.djangoapps.lti_provider.urls')),
|
||||
]
|
||||
|
||||
urlpatterns += [
|
||||
|
||||
@@ -13,7 +13,7 @@ from path import Path
|
||||
# TODO: Remove the rest of the sys.path modification here and in (cms|lms)/envs/common.py
|
||||
REPO_ROOT = Path(__file__).abspath().dirname().dirname().dirname() # /edx-platform/
|
||||
sys.path.append(REPO_ROOT / 'common' / 'djangoapps')
|
||||
sys.path.append(REPO_ROOT / 'lms' / 'djangoapps')
|
||||
sys.path.append(REPO_ROOT / 'sys_path_hacks' / 'lms')
|
||||
|
||||
ALL_LANGUAGES = []
|
||||
|
||||
@@ -90,7 +90,7 @@ INSTALLED_APPS = (
|
||||
'openedx.core.djangoapps.external_user_ids',
|
||||
'openedx.core.djangoapps.demographics',
|
||||
|
||||
'experiments',
|
||||
'lms.djangoapps.experiments',
|
||||
'openedx.features.content_type_gating',
|
||||
'openedx.features.course_duration_limits',
|
||||
'openedx.features.discounts',
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import warnings
|
||||
warnings.warn("Importing courseware.management.commands.import instead of lms.djangoapps.courseware.management.commands.import is deprecated", stacklevel=2)
|
||||
|
||||
from lms.djangoapps.courseware.management.commands.import import *
|
||||
Reference in New Issue
Block a user