Commit 986dcff6 by wajeeha-khalid

MA-2536: get 'course_about' url in enrollment

parent cad10c23
...@@ -219,6 +219,7 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin): ...@@ -219,6 +219,7 @@ class CourseDetailsViewTest(CourseTestCase, MilestonesTestCaseMixin):
(False, True, False), (False, True, False),
(True, True, True), (True, True, True),
) )
@override_settings(MKTG_URLS={'ROOT': 'dummy-root'})
def test_visibility_of_entrance_exam_section(self, feature_flags): def test_visibility_of_entrance_exam_section(self, feature_flags):
""" """
Tests entrance exam section is available if ENTRANCE_EXAMS feature is enabled no matter any other Tests entrance exam section is available if ENTRANCE_EXAMS feature is enabled no matter any other
...@@ -1161,6 +1162,7 @@ id=\"course-enrollment-end-time\" value=\"\" placeholder=\"HH:MM\" autocomplete= ...@@ -1161,6 +1162,7 @@ id=\"course-enrollment-end-time\" value=\"\" placeholder=\"HH:MM\" autocomplete=
self._verify_editable(self._get_course_details_response(False)) self._verify_editable(self._get_course_details_response(False))
@mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_MKTG_SITE': True}) @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_MKTG_SITE': True})
@override_settings(MKTG_URLS={'ROOT': 'dummy-root'})
def test_course_details_with_enabled_setting_global_staff(self): def test_course_details_with_enabled_setting_global_staff(self):
""" Test that user enrollment end date is editable in response. """ Test that user enrollment end date is editable in response.
...@@ -1170,6 +1172,7 @@ id=\"course-enrollment-end-time\" value=\"\" placeholder=\"HH:MM\" autocomplete= ...@@ -1170,6 +1172,7 @@ id=\"course-enrollment-end-time\" value=\"\" placeholder=\"HH:MM\" autocomplete=
self._verify_editable(self._get_course_details_response(True)) self._verify_editable(self._get_course_details_response(True))
@mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_MKTG_SITE': True}) @mock.patch.dict("django.conf.settings.FEATURES", {'ENABLE_MKTG_SITE': True})
@override_settings(MKTG_URLS={'ROOT': 'dummy-root'})
def test_course_details_with_enabled_setting_non_global_staff(self): def test_course_details_with_enabled_setting_non_global_staff(self):
""" Test that user enrollment end date is not editable in response. """ Test that user enrollment end date is not editable in response.
......
...@@ -2,10 +2,8 @@ ...@@ -2,10 +2,8 @@
import collections import collections
from datetime import datetime, timedelta from datetime import datetime, timedelta
import mock
from pytz import UTC from pytz import UTC
from django.test import TestCase from django.test import TestCase
from django.test.utils import override_settings
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
...@@ -20,53 +18,6 @@ from contentstore.tests.utils import CourseTestCase ...@@ -20,53 +18,6 @@ from contentstore.tests.utils import CourseTestCase
class LMSLinksTestCase(TestCase): class LMSLinksTestCase(TestCase):
""" Tests for LMS links. """ """ Tests for LMS links. """
def about_page_test(self):
""" Get URL for about page, no marketing site """
# default for ENABLE_MKTG_SITE is False.
self.assertEquals(self.get_about_page_link(), "//localhost:8000/courses/mitX/101/test/about")
@override_settings(MKTG_URLS={'ROOT': 'dummy-root'})
def about_page_marketing_site_test(self):
""" Get URL for about page, marketing root present. """
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': True}):
self.assertEquals(self.get_about_page_link(), "//dummy-root/courses/mitX/101/test/about")
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': False}):
self.assertEquals(self.get_about_page_link(), "//localhost:8000/courses/mitX/101/test/about")
@override_settings(MKTG_URLS={'ROOT': 'http://www.dummy'})
def about_page_marketing_site_remove_http_test(self):
""" Get URL for about page, marketing root present, remove http://. """
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': True}):
self.assertEquals(self.get_about_page_link(), "//www.dummy/courses/mitX/101/test/about")
@override_settings(MKTG_URLS={'ROOT': 'https://www.dummy'})
def about_page_marketing_site_remove_https_test(self):
""" Get URL for about page, marketing root present, remove https://. """
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': True}):
self.assertEquals(self.get_about_page_link(), "//www.dummy/courses/mitX/101/test/about")
@override_settings(MKTG_URLS={'ROOT': 'www.dummyhttps://x'})
def about_page_marketing_site_https__edge_test(self):
""" Get URL for about page, only remove https:// at the beginning of the string. """
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': True}):
self.assertEquals(self.get_about_page_link(), "//www.dummyhttps://x/courses/mitX/101/test/about")
@override_settings(MKTG_URLS={})
def about_page_marketing_urls_not_set_test(self):
""" Error case. ENABLE_MKTG_SITE is True, but there is either no MKTG_URLS, or no MKTG_URLS Root property. """
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': True}):
self.assertEquals(self.get_about_page_link(), None)
@override_settings(LMS_BASE=None)
def about_page_no_lms_base_test(self):
""" No LMS_BASE, nor is ENABLE_MKTG_SITE True """
self.assertEquals(self.get_about_page_link(), None)
def get_about_page_link(self):
""" create mock course and return the about page link """
course_key = SlashSeparatedCourseKey('mitX', '101', 'test')
return utils.get_lms_link_for_about_page(course_key)
def lms_link_test(self): def lms_link_test(self):
""" Tests get_lms_link_for_item. """ """ Tests get_lms_link_for_item. """
course_key = SlashSeparatedCourseKey('mitX', '101', 'test') course_key = SlashSeparatedCourseKey('mitX', '101', 'test')
......
...@@ -104,42 +104,6 @@ def get_lms_link_for_item(location, preview=False): ...@@ -104,42 +104,6 @@ def get_lms_link_for_item(location, preview=False):
) )
def get_lms_link_for_about_page(course_key):
"""
Returns the url to the course about page from the location tuple.
"""
assert isinstance(course_key, CourseKey)
if settings.FEATURES.get('ENABLE_MKTG_SITE', False):
if not hasattr(settings, 'MKTG_URLS'):
log.exception("ENABLE_MKTG_SITE is True, but MKTG_URLS is not defined.")
return None
marketing_urls = settings.MKTG_URLS
# Root will be "https://www.edx.org". The complete URL will still not be exactly correct,
# but redirects exist from www.edx.org to get to the Drupal course about page URL.
about_base = marketing_urls.get('ROOT', None)
if about_base is None:
log.exception('There is no ROOT defined in MKTG_URLS')
return None
# Strip off https:// (or http://) to be consistent with the formatting of LMS_BASE.
about_base = re.sub(r"^https?://", "", about_base)
elif settings.LMS_BASE is not None:
about_base = settings.LMS_BASE
else:
return None
return u"//{about_base_url}/courses/{course_key}/about".format(
about_base_url=about_base,
course_key=course_key.to_deprecated_string()
)
# pylint: disable=invalid-name # pylint: disable=invalid-name
def get_lms_link_for_certificate_web_view(user_id, course_key, mode): def get_lms_link_for_certificate_web_view(user_id, course_key, mode):
""" """
......
...@@ -28,7 +28,6 @@ from .component import ( ...@@ -28,7 +28,6 @@ from .component import (
from .item import create_xblock_info from .item import create_xblock_info
from .library import LIBRARIES_ENABLED from .library import LIBRARIES_ENABLED
from ccx_keys.locator import CCXLocator from ccx_keys.locator import CCXLocator
from contentstore import utils
from contentstore.course_group_config import ( from contentstore.course_group_config import (
COHORT_SCHEME, COHORT_SCHEME,
GroupConfiguration, GroupConfiguration,
...@@ -77,6 +76,7 @@ from student.auth import has_course_author_access, has_studio_write_access, has_ ...@@ -77,6 +76,7 @@ from student.auth import has_course_author_access, has_studio_write_access, has_
from student.roles import ( from student.roles import (
CourseInstructorRole, CourseStaffRole, CourseCreatorRole, GlobalStaff, UserBasedRole CourseInstructorRole, CourseStaffRole, CourseCreatorRole, GlobalStaff, UserBasedRole
) )
from util.course import get_lms_link_for_about_page
from util.date_utils import get_default_time_display from util.date_utils import get_default_time_display
from util.json_request import JsonResponse, JsonResponseBadRequest, expect_json from util.json_request import JsonResponse, JsonResponseBadRequest, expect_json
from util.milestones_helpers import ( from util.milestones_helpers import (
...@@ -996,7 +996,7 @@ def settings_handler(request, course_key_string): ...@@ -996,7 +996,7 @@ def settings_handler(request, course_key_string):
settings_context = { settings_context = {
'context_course': course_module, 'context_course': course_module,
'course_locator': course_key, 'course_locator': course_key,
'lms_link_for_about_page': utils.get_lms_link_for_about_page(course_key), 'lms_link_for_about_page': get_lms_link_for_about_page(course_key),
'course_image_url': course_image_url(course_module, 'course_image'), 'course_image_url': course_image_url(course_module, 'course_image'),
'banner_image_url': course_image_url(course_module, 'banner_image'), 'banner_image_url': course_image_url(course_module, 'banner_image'),
'video_thumbnail_image_url': course_image_url(course_module, 'video_thumbnail_image'), 'video_thumbnail_image_url': course_image_url(course_module, 'video_thumbnail_image'),
......
...@@ -138,6 +138,7 @@ EMAIL_PORT = ENV_TOKENS.get('EMAIL_PORT', EMAIL_PORT) ...@@ -138,6 +138,7 @@ EMAIL_PORT = ENV_TOKENS.get('EMAIL_PORT', EMAIL_PORT)
EMAIL_USE_TLS = ENV_TOKENS.get('EMAIL_USE_TLS', EMAIL_USE_TLS) EMAIL_USE_TLS = ENV_TOKENS.get('EMAIL_USE_TLS', EMAIL_USE_TLS)
LMS_BASE = ENV_TOKENS.get('LMS_BASE') LMS_BASE = ENV_TOKENS.get('LMS_BASE')
LMS_ROOT_URL = ENV_TOKENS.get('LMS_ROOT_URL')
# Note that FEATURES['PREVIEW_LMS_BASE'] gets read in from the environment file. # Note that FEATURES['PREVIEW_LMS_BASE'] gets read in from the environment file.
SITE_NAME = ENV_TOKENS['SITE_NAME'] SITE_NAME = ENV_TOKENS['SITE_NAME']
......
...@@ -88,6 +88,7 @@ ...@@ -88,6 +88,7 @@
"STORAGE_TYPE": "localfs" "STORAGE_TYPE": "localfs"
}, },
"LMS_BASE": "localhost:8003", "LMS_BASE": "localhost:8003",
"LMS_ROOT_URL": "http://localhost:8003",
"LOCAL_LOGLEVEL": "INFO", "LOCAL_LOGLEVEL": "INFO",
"LOGGING_ENV": "sandbox", "LOGGING_ENV": "sandbox",
"LOG_DIR": "** OVERRIDDEN **", "LOG_DIR": "** OVERRIDDEN **",
......
...@@ -120,6 +120,8 @@ MOCK_SEARCH_BACKING_FILE = ( ...@@ -120,6 +120,8 @@ MOCK_SEARCH_BACKING_FILE = (
# this secret key should be the same as lms/envs/bok_choy.py's # this secret key should be the same as lms/envs/bok_choy.py's
SECRET_KEY = "very_secret_bok_choy_key" SECRET_KEY = "very_secret_bok_choy_key"
LMS_ROOT_URL = "http://localhost:8000"
##################################################################### #####################################################################
# Lastly, see if the developer has any local overrides. # Lastly, see if the developer has any local overrides.
try: try:
......
...@@ -296,6 +296,7 @@ AUTHENTICATION_BACKENDS = ( ...@@ -296,6 +296,7 @@ AUTHENTICATION_BACKENDS = (
) )
LMS_BASE = None LMS_BASE = None
LMS_ROOT_URL = "http://localhost:8000"
# These are standard regexes for pulling out info like course_ids, usage_ids, etc. # These are standard regexes for pulling out info like course_ids, usage_ids, etc.
# They are used so that URLs with deprecated-format strings still work. # They are used so that URLs with deprecated-format strings still work.
......
...@@ -60,6 +60,7 @@ DATABASES = { ...@@ -60,6 +60,7 @@ DATABASES = {
} }
LMS_BASE = "localhost:8000" LMS_BASE = "localhost:8000"
LMS_ROOT_URL = "http://{}".format(LMS_BASE)
FEATURES['PREVIEW_LMS_BASE'] = "localhost:8000" FEATURES['PREVIEW_LMS_BASE'] = "localhost:8000"
REPOS = { REPOS = {
......
...@@ -31,6 +31,7 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' ...@@ -31,6 +31,7 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
################################# LMS INTEGRATION ############################# ################################# LMS INTEGRATION #############################
LMS_BASE = "localhost:8000" LMS_BASE = "localhost:8000"
LMS_ROOT_URL = "http://{}".format(LMS_BASE)
FEATURES['PREVIEW_LMS_BASE'] = "preview." + LMS_BASE FEATURES['PREVIEW_LMS_BASE'] = "preview." + LMS_BASE
########################### PIPELINE ################################# ########################### PIPELINE #################################
......
...@@ -141,6 +141,7 @@ if os.environ.get('DISABLE_MIGRATIONS'): ...@@ -141,6 +141,7 @@ if os.environ.get('DISABLE_MIGRATIONS'):
MIGRATION_MODULES = NoOpMigrationModules() MIGRATION_MODULES = NoOpMigrationModules()
LMS_BASE = "localhost:8000" LMS_BASE = "localhost:8000"
LMS_ROOT_URL = "http://{}".format(LMS_BASE)
FEATURES['PREVIEW_LMS_BASE'] = "preview.localhost" FEATURES['PREVIEW_LMS_BASE'] = "preview.localhost"
......
...@@ -5,6 +5,7 @@ Module with code executed during Studio startup ...@@ -5,6 +5,7 @@ Module with code executed during Studio startup
from django.conf import settings from django.conf import settings
# Force settings to run so that the python path is modified # Force settings to run so that the python path is modified
settings.INSTALLED_APPS # pylint: disable=pointless-statement settings.INSTALLED_APPS # pylint: disable=pointless-statement
from openedx.core.lib.django_startup import autostartup from openedx.core.lib.django_startup import autostartup
...@@ -18,6 +19,7 @@ from openedx.core.lib.xblock_utils import xblock_local_resource_url ...@@ -18,6 +19,7 @@ from openedx.core.lib.xblock_utils import xblock_local_resource_url
import xmodule.x_module import xmodule.x_module
import cms.lib.xblock.runtime import cms.lib.xblock.runtime
from startup_configurations.validate_config import validate_cms_config
from openedx.core.djangoapps.theming.core import enable_theming from openedx.core.djangoapps.theming.core import enable_theming
from openedx.core.djangoapps.theming.helpers import is_comprehensive_theming_enabled from openedx.core.djangoapps.theming.helpers import is_comprehensive_theming_enabled
...@@ -47,6 +49,9 @@ def run(): ...@@ -47,6 +49,9 @@ def run():
xmodule.x_module.descriptor_global_handler_url = cms.lib.xblock.runtime.handler_url xmodule.x_module.descriptor_global_handler_url = cms.lib.xblock.runtime.handler_url
xmodule.x_module.descriptor_global_local_resource_url = xblock_local_resource_url xmodule.x_module.descriptor_global_local_resource_url = xblock_local_resource_url
# validate configurations on startup
validate_cms_config(settings)
def add_mimetypes(): def add_mimetypes():
""" """
......
"""
Common Functions to Validate Configurations
"""
def validate_lms_config(settings):
"""
Validates configurations for lms and raise ValueError if not valid
"""
validate_common_config(settings)
# validate feature based configurations
validate_marketing_site_config(settings)
def validate_cms_config(settings):
"""
Validates configurations for lms and raise ValueError if not valid
"""
validate_common_config(settings)
# validate feature based configurations
validate_marketing_site_config(settings)
def validate_common_config(settings):
"""
Validates configurations common for all apps
"""
if not getattr(settings, 'LMS_ROOT_URL', None):
raise ValueError("'LMS_ROOT_URL' is not defined.")
def validate_marketing_site_config(settings):
"""
Validates 'marketing site' related configurations
"""
if settings.FEATURES.get('ENABLE_MKTG_SITE'):
if not hasattr(settings, 'MKTG_URLS'):
raise ValueError("'ENABLE_MKTG_SITE' is True, but 'MKTG_URLS' is not defined.")
if not settings.MKTG_URLS.get('ROOT'):
raise ValueError("There is no 'ROOT' defined in 'MKTG_URLS'.")
"""
Utility methods related to course
"""
import logging
from django.conf import settings
from opaque_keys.edx.keys import CourseKey
log = logging.getLogger(__name__)
def get_lms_link_for_about_page(course_key):
"""
Returns the url to the course about page.
"""
assert isinstance(course_key, CourseKey)
if settings.FEATURES.get('ENABLE_MKTG_SITE'):
# Root will be "https://www.edx.org". The complete URL will still not be exactly correct,
# but redirects exist from www.edx.org to get to the Drupal course about page URL.
about_base = settings.MKTG_URLS['ROOT']
else:
about_base = settings.LMS_ROOT_URL
return u"{about_base_url}/courses/{course_key}/about".format(
about_base_url=about_base,
course_key=course_key.to_deprecated_string()
)
"""
Tests for course utils.
"""
from django.test import TestCase, override_settings
import mock
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from util.course import get_lms_link_for_about_page
class LmsLinksTestCase(TestCase):
""" Tests for LMS links. """
def test_about_page(self):
""" Get URL for about page, no marketing site """
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': False}):
self.assertEquals(self.get_about_page_link(), "http://localhost:8000/courses/mitX/101/test/about")
@override_settings(MKTG_URLS={'ROOT': 'https://dummy-root'})
def test_about_page_marketing_site(self):
""" Get URL for about page, marketing root present. """
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': True}):
self.assertEquals(self.get_about_page_link(), "https://dummy-root/courses/mitX/101/test/about")
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': False}):
self.assertEquals(self.get_about_page_link(), "http://localhost:8000/courses/mitX/101/test/about")
@override_settings(MKTG_URLS={'ROOT': 'https://www.dummyhttps://x'})
def test_about_page_marketing_site_https__edge(self):
""" Get URL for about page """
with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': True}):
self.assertEquals(self.get_about_page_link(), "https://www.dummyhttps://x/courses/mitX/101/test/about")
def get_about_page_link(self):
""" create mock course and return the about page link."""
course_key = SlashSeparatedCourseKey('mitX', '101', 'test')
return get_lms_link_for_about_page(course_key)
""" """
Milestone related tests for the mobile_api Milestone related tests for the mobile_api
""" """
from django.conf import settings
from mock import patch from mock import patch
from courseware.access_response import MilestoneError from courseware.access_response import MilestoneError
...@@ -26,14 +27,22 @@ class MobileAPIMilestonesMixin(object): ...@@ -26,14 +27,22 @@ class MobileAPIMilestonesMixin(object):
ALLOW_ACCESS_TO_MILESTONE_COURSE = False # pylint: disable=invalid-name ALLOW_ACCESS_TO_MILESTONE_COURSE = False # pylint: disable=invalid-name
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PREREQUISITE_COURSES': True, 'MILESTONES_APP': True}) @patch.dict(settings.FEATURES, {
'ENABLE_PREREQUISITE_COURSES': True,
'MILESTONES_APP': True,
'ENABLE_MKTG_SITE': True,
})
def test_unfulfilled_prerequisite_course(self): def test_unfulfilled_prerequisite_course(self):
""" Tests the case for an unfulfilled pre-requisite course """ """ Tests the case for an unfulfilled pre-requisite course """
self._add_prerequisite_course() self._add_prerequisite_course()
self.init_course_access() self.init_course_access()
self._verify_unfulfilled_milestone_response() self._verify_unfulfilled_milestone_response()
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PREREQUISITE_COURSES': True, 'MILESTONES_APP': True}) @patch.dict(settings.FEATURES, {
'ENABLE_PREREQUISITE_COURSES': True,
'MILESTONES_APP': True,
'ENABLE_MKTG_SITE': True,
})
def test_unfulfilled_prerequisite_course_for_staff(self): def test_unfulfilled_prerequisite_course_for_staff(self):
self._add_prerequisite_course() self._add_prerequisite_course()
self.user.is_staff = True self.user.is_staff = True
...@@ -41,7 +50,11 @@ class MobileAPIMilestonesMixin(object): ...@@ -41,7 +50,11 @@ class MobileAPIMilestonesMixin(object):
self.init_course_access() self.init_course_access()
self.api_response() self.api_response()
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PREREQUISITE_COURSES': True, 'MILESTONES_APP': True}) @patch.dict(settings.FEATURES, {
'ENABLE_PREREQUISITE_COURSES': True,
'MILESTONES_APP': True,
'ENABLE_MKTG_SITE': True,
})
def test_fulfilled_prerequisite_course(self): def test_fulfilled_prerequisite_course(self):
""" """
Tests the case when a user fulfills existing pre-requisite course Tests the case when a user fulfills existing pre-requisite course
...@@ -52,7 +65,11 @@ class MobileAPIMilestonesMixin(object): ...@@ -52,7 +65,11 @@ class MobileAPIMilestonesMixin(object):
self.init_course_access() self.init_course_access()
self.api_response() self.api_response()
@patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': True, 'MILESTONES_APP': True}) @patch.dict(settings.FEATURES, {
'ENTRANCE_EXAMS': True,
'MILESTONES_APP': True,
'ENABLE_MKTG_SITE': True,
})
def test_unpassed_entrance_exam(self): def test_unpassed_entrance_exam(self):
""" """
Tests the case where the user has not passed the entrance exam Tests the case where the user has not passed the entrance exam
...@@ -61,7 +78,11 @@ class MobileAPIMilestonesMixin(object): ...@@ -61,7 +78,11 @@ class MobileAPIMilestonesMixin(object):
self.init_course_access() self.init_course_access()
self._verify_unfulfilled_milestone_response() self._verify_unfulfilled_milestone_response()
@patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': True, 'MILESTONES_APP': True}) @patch.dict(settings.FEATURES, {
'ENTRANCE_EXAMS': True,
'MILESTONES_APP': True,
'ENABLE_MKTG_SITE': True,
})
def test_unpassed_entrance_exam_for_staff(self): def test_unpassed_entrance_exam_for_staff(self):
self._add_entrance_exam() self._add_entrance_exam()
self.user.is_staff = True self.user.is_staff = True
...@@ -69,7 +90,11 @@ class MobileAPIMilestonesMixin(object): ...@@ -69,7 +90,11 @@ class MobileAPIMilestonesMixin(object):
self.init_course_access() self.init_course_access()
self.api_response() self.api_response()
@patch.dict('django.conf.settings.FEATURES', {'ENTRANCE_EXAMS': True, 'MILESTONES_APP': True}) @patch.dict(settings.FEATURES, {
'ENTRANCE_EXAMS': True,
'MILESTONES_APP': True,
'ENABLE_MKTG_SITE': True,
})
def test_passed_entrance_exam(self): def test_passed_entrance_exam(self):
""" """
Tests access when user has passed the entrance exam Tests access when user has passed the entrance exam
......
...@@ -11,6 +11,7 @@ Test utilities for mobile API tests: ...@@ -11,6 +11,7 @@ Test utilities for mobile API tests:
""" """
# pylint: disable=no-member # pylint: disable=no-member
from datetime import timedelta from datetime import timedelta
from django.conf import settings
from django.utils import timezone from django.utils import timezone
import ddt import ddt
...@@ -153,6 +154,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin): ...@@ -153,6 +154,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin):
"""Base implementation of initializing the user for each test.""" """Base implementation of initializing the user for each test."""
self.login_and_enroll(course_id) self.login_and_enroll(course_id)
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
def test_success(self): def test_success(self):
self.init_course_access() self.init_course_access()
...@@ -166,7 +168,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin): ...@@ -166,7 +168,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin):
response = self.api_response(expected_response_code=None, course_id=non_existent_course_id) response = self.api_response(expected_response_code=None, course_id=non_existent_course_id)
self.verify_failure(response) # allow subclasses to override verification self.verify_failure(response) # allow subclasses to override verification
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False}) @patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False, 'ENABLE_MKTG_SITE': True})
def test_unreleased_course(self): def test_unreleased_course(self):
# ensure the course always starts in the future # ensure the course always starts in the future
# pylint: disable=attribute-defined-outside-init # pylint: disable=attribute-defined-outside-init
...@@ -184,6 +186,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin): ...@@ -184,6 +186,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin):
(None, False) (None, False)
) )
@ddt.unpack @ddt.unpack
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
def test_non_mobile_available(self, role, should_succeed): def test_non_mobile_available(self, role, should_succeed):
self.init_course_access() self.init_course_access()
# set mobile_available to False for the test course # set mobile_available to False for the test course
...@@ -202,6 +205,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin): ...@@ -202,6 +205,7 @@ class MobileCourseAccessTestMixin(MobileAPIMilestonesMixin):
(None, False) (None, False)
) )
@ddt.unpack @ddt.unpack
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
def test_visible_to_staff_only_course(self, role, should_succeed): def test_visible_to_staff_only_course(self, role, should_succeed):
self.init_course_access() self.init_course_access()
self.course.visible_to_staff_only = True self.course.visible_to_staff_only = True
......
""" """
Serializer for user API Serializer for user API
""" """
from opaque_keys.edx.keys import CourseKey
from rest_framework import serializers from rest_framework import serializers
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
from courseware.access import has_access from courseware.access import has_access
from student.models import CourseEnrollment, User from student.models import CourseEnrollment, User
from certificates.api import certificate_downloadable_status from certificates.api import certificate_downloadable_status
from util.course import get_lms_link_for_about_page
class CourseOverviewField(serializers.RelatedField): class CourseOverviewField(serializers.RelatedField):
...@@ -50,11 +52,7 @@ class CourseOverviewField(serializers.RelatedField): ...@@ -50,11 +52,7 @@ class CourseOverviewField(serializers.RelatedField):
} }
}, },
'course_image': course_overview.course_image_url, 'course_image': course_overview.course_image_url,
'course_about': reverse( 'course_about': get_lms_link_for_about_page(CourseKey.from_string(course_id)),
'about_course',
kwargs={'course_id': course_id},
request=request,
),
'course_updates': reverse( 'course_updates': reverse(
'course-updates-list', 'course-updates-list',
kwargs={'course_id': course_id}, kwargs={'course_id': course_id},
......
...@@ -11,7 +11,7 @@ import pytz ...@@ -11,7 +11,7 @@ import pytz
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone
from django.template import defaultfilters from django.template import defaultfilters
from django.test import RequestFactory from django.test import RequestFactory, override_settings
from milestones.tests.utils import MilestonesTestCaseMixin from milestones.tests.utils import MilestonesTestCaseMixin
from xmodule.course_module import DEFAULT_START_DATE from xmodule.course_module import DEFAULT_START_DATE
from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory
...@@ -73,6 +73,7 @@ class TestUserInfoApi(MobileAPITestCase, MobileAuthTestMixin): ...@@ -73,6 +73,7 @@ class TestUserInfoApi(MobileAPITestCase, MobileAuthTestMixin):
@attr('shard_2') @attr('shard_2')
@ddt.ddt @ddt.ddt
@override_settings(MKTG_URLS={'ROOT': 'dummy-root'})
class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTestMixin, class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTestMixin,
MobileCourseAccessTestMixin, MilestonesTestCaseMixin): MobileCourseAccessTestMixin, MilestonesTestCaseMixin):
""" """
...@@ -86,7 +87,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest ...@@ -86,7 +87,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
LAST_WEEK = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=7) LAST_WEEK = datetime.datetime.now(pytz.UTC) - datetime.timedelta(days=7)
ADVERTISED_START = "Spring 2016" ADVERTISED_START = "Spring 2016"
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True}) @patch.dict(settings.FEATURES, {"ENABLE_DISCUSSION_SERVICE": True})
def setUp(self, *args, **kwargs): def setUp(self, *args, **kwargs):
super(TestUserEnrollmentApi, self).setUp() super(TestUserEnrollmentApi, self).setUp()
...@@ -117,6 +118,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest ...@@ -117,6 +118,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
courses = response.data courses = response.data
self.assertEqual(len(courses), 0) self.assertEqual(len(courses), 0)
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
def test_sort_order(self): def test_sort_order(self):
self.login() self.login()
...@@ -134,9 +136,12 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest ...@@ -134,9 +136,12 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
unicode(courses[num_courses - course_index - 1].id) unicode(courses[num_courses - course_index - 1].id)
) )
@patch.dict( @patch.dict(settings.FEATURES, {
settings.FEATURES, {'ENABLE_PREREQUISITE_COURSES': True, 'MILESTONES_APP': True, 'DISABLE_START_DATES': False} 'ENABLE_PREREQUISITE_COURSES': True,
) 'MILESTONES_APP': True,
'DISABLE_START_DATES': False,
'ENABLE_MKTG_SITE': True,
})
def test_courseware_access(self): def test_courseware_access(self):
self.login() self.login()
...@@ -181,7 +186,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest ...@@ -181,7 +186,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
(DEFAULT_START_DATE, None, None, "empty"), (DEFAULT_START_DATE, None, None, "empty"),
) )
@ddt.unpack @ddt.unpack
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False}) @patch.dict(settings.FEATURES, {'DISABLE_START_DATES': False, 'ENABLE_MKTG_SITE': True})
def test_start_type_and_display(self, start, advertised_start, expected_display, expected_type): def test_start_type_and_display(self, start, advertised_start, expected_display, expected_type):
""" """
Tests that the correct start_type and start_display are returned in the Tests that the correct start_type and start_display are returned in the
...@@ -195,6 +200,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest ...@@ -195,6 +200,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
self.assertEqual(response.data[0]['course']['start_type'], expected_type) self.assertEqual(response.data[0]['course']['start_type'], expected_type)
self.assertEqual(response.data[0]['course']['start_display'], expected_display) self.assertEqual(response.data[0]['course']['start_display'], expected_display)
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
def test_no_certificate(self): def test_no_certificate(self):
self.login_and_enroll() self.login_and_enroll()
...@@ -222,21 +228,21 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest ...@@ -222,21 +228,21 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
certificate_data = response.data[0]['certificate'] certificate_data = response.data[0]['certificate']
self.assertEquals(certificate_data['url'], certificate_url) self.assertEquals(certificate_data['url'], certificate_url)
@patch.dict(settings.FEATURES, {'CERTIFICATES_HTML_VIEW': False}) @patch.dict(settings.FEATURES, {'CERTIFICATES_HTML_VIEW': False, 'ENABLE_MKTG_SITE': True})
def test_pdf_certificate_with_html_cert_disabled(self): def test_pdf_certificate_with_html_cert_disabled(self):
""" """
Tests PDF certificates with CERTIFICATES_HTML_VIEW set to False. Tests PDF certificates with CERTIFICATES_HTML_VIEW set to False.
""" """
self.verify_pdf_certificate() self.verify_pdf_certificate()
@patch.dict(settings.FEATURES, {'CERTIFICATES_HTML_VIEW': True}) @patch.dict(settings.FEATURES, {'CERTIFICATES_HTML_VIEW': True, 'ENABLE_MKTG_SITE': True})
def test_pdf_certificate_with_html_cert_enabled(self): def test_pdf_certificate_with_html_cert_enabled(self):
""" """
Tests PDF certificates with CERTIFICATES_HTML_VIEW set to True. Tests PDF certificates with CERTIFICATES_HTML_VIEW set to True.
""" """
self.verify_pdf_certificate() self.verify_pdf_certificate()
@patch.dict(settings.FEATURES, {'CERTIFICATES_HTML_VIEW': True}) @patch.dict(settings.FEATURES, {'CERTIFICATES_HTML_VIEW': True, 'ENABLE_MKTG_SITE': True})
def test_web_certificate(self): def test_web_certificate(self):
CourseMode.objects.create( CourseMode.objects.create(
course_id=self.course.id, course_id=self.course.id,
...@@ -261,7 +267,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest ...@@ -261,7 +267,7 @@ class TestUserEnrollmentApi(UrlResetMixin, MobileAPITestCase, MobileAuthUserTest
) )
) )
@patch.dict("django.conf.settings.FEATURES", {"ENABLE_DISCUSSION_SERVICE": True}) @patch.dict(settings.FEATURES, {"ENABLE_DISCUSSION_SERVICE": True, 'ENABLE_MKTG_SITE': True})
def test_discussion_url(self): def test_discussion_url(self):
self.login_and_enroll() self.login_and_enroll()
...@@ -430,6 +436,8 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin, ...@@ -430,6 +436,8 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin,
@attr('shard_2') @attr('shard_2')
@patch.dict(settings.FEATURES, {'ENABLE_MKTG_SITE': True})
@override_settings(MKTG_URLS={'ROOT': 'dummy-root'})
class TestCourseEnrollmentSerializer(MobileAPITestCase, MilestonesTestCaseMixin): class TestCourseEnrollmentSerializer(MobileAPITestCase, MilestonesTestCaseMixin):
""" """
Test the course enrollment serializer Test the course enrollment serializer
......
...@@ -188,6 +188,8 @@ REGISTRATION_EMAIL_PATTERNS_ALLOWED = ENV_TOKENS.get('REGISTRATION_EMAIL_PATTERN ...@@ -188,6 +188,8 @@ REGISTRATION_EMAIL_PATTERNS_ALLOWED = ENV_TOKENS.get('REGISTRATION_EMAIL_PATTERN
EDXMKTG_LOGGED_IN_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_LOGGED_IN_COOKIE_NAME', EDXMKTG_LOGGED_IN_COOKIE_NAME) EDXMKTG_LOGGED_IN_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_LOGGED_IN_COOKIE_NAME', EDXMKTG_LOGGED_IN_COOKIE_NAME)
EDXMKTG_USER_INFO_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_USER_INFO_COOKIE_NAME', EDXMKTG_USER_INFO_COOKIE_NAME) EDXMKTG_USER_INFO_COOKIE_NAME = ENV_TOKENS.get('EDXMKTG_USER_INFO_COOKIE_NAME', EDXMKTG_USER_INFO_COOKIE_NAME)
LMS_ROOT_URL = ENV_TOKENS.get('LMS_ROOT_URL')
ENV_FEATURES = ENV_TOKENS.get('FEATURES', {}) ENV_FEATURES = ENV_TOKENS.get('FEATURES', {})
for feature, value in ENV_FEATURES.items(): for feature, value in ENV_FEATURES.items():
FEATURES[feature] = value FEATURES[feature] = value
......
...@@ -96,6 +96,7 @@ ...@@ -96,6 +96,7 @@
"JWT_SECRET_KEY": "super-secret-key" "JWT_SECRET_KEY": "super-secret-key"
}, },
"LMS_BASE": "localhost:8003", "LMS_BASE": "localhost:8003",
"LMS_ROOT_URL": "http://localhost:8003",
"LOCAL_LOGLEVEL": "INFO", "LOCAL_LOGLEVEL": "INFO",
"LOGGING_ENV": "sandbox", "LOGGING_ENV": "sandbox",
"LOG_DIR": "** OVERRIDDEN **", "LOG_DIR": "** OVERRIDDEN **",
......
...@@ -193,6 +193,8 @@ BADGING_BACKEND = 'lms.djangoapps.badges.backends.tests.dummy_backend.DummyBacke ...@@ -193,6 +193,8 @@ BADGING_BACKEND = 'lms.djangoapps.badges.backends.tests.dummy_backend.DummyBacke
ECOMMERCE_API_URL = 'http://localhost:8043/api/v2/' ECOMMERCE_API_URL = 'http://localhost:8043/api/v2/'
ECOMMERCE_API_SIGNING_KEY = 'ecommerce-key' ECOMMERCE_API_SIGNING_KEY = 'ecommerce-key'
LMS_ROOT_URL = "http://localhost:8000"
##################################################################### #####################################################################
# Lastly, see if the developer has any local overrides. # Lastly, see if the developer has any local overrides.
try: try:
......
...@@ -60,6 +60,7 @@ DISCUSSION_SETTINGS = { ...@@ -60,6 +60,7 @@ DISCUSSION_SETTINGS = {
'MAX_COMMENT_DEPTH': 2, 'MAX_COMMENT_DEPTH': 2,
} }
LMS_ROOT_URL = "http://localhost:8000"
# Features # Features
FEATURES = { FEATURES = {
......
...@@ -27,6 +27,7 @@ FEATURES['AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING'] = True ...@@ -27,6 +27,7 @@ FEATURES['AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING'] = True
FEATURES['ENABLE_GRADE_DOWNLOADS'] = True FEATURES['ENABLE_GRADE_DOWNLOADS'] = True
FEATURES['ENABLE_PAYMENT_FAKE'] = True FEATURES['ENABLE_PAYMENT_FAKE'] = True
LMS_ROOT_URL = "http://localhost:8000"
FEEDBACK_SUBMISSION_EMAIL = "dummy@example.com" FEEDBACK_SUBMISSION_EMAIL = "dummy@example.com"
......
...@@ -19,6 +19,8 @@ PLATFORM_NAME = ENV_TOKENS.get('PLATFORM_NAME', 'Devstack') ...@@ -19,6 +19,8 @@ PLATFORM_NAME = ENV_TOKENS.get('PLATFORM_NAME', 'Devstack')
CELERY_ALWAYS_EAGER = True CELERY_ALWAYS_EAGER = True
HTTPS = 'off' HTTPS = 'off'
LMS_ROOT_URL = 'http://localhost:8000'
################################ LOGGERS ###################################### ################################ LOGGERS ######################################
# Silence noisy logs # Silence noisy logs
......
...@@ -585,3 +585,5 @@ OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application' ...@@ -585,3 +585,5 @@ OAUTH2_PROVIDER_APPLICATION_MODEL = 'oauth2_provider.Application'
COURSE_CATALOG_API_URL = 'https://catalog.example.com/api/v1' COURSE_CATALOG_API_URL = 'https://catalog.example.com/api/v1'
COMPREHENSIVE_THEME_DIRS = [REPO_ROOT / "themes", REPO_ROOT / "common/test"] COMPREHENSIVE_THEME_DIRS = [REPO_ROOT / "themes", REPO_ROOT / "common/test"]
LMS_ROOT_URL = "http://localhost:8000"
...@@ -6,6 +6,7 @@ import django ...@@ -6,6 +6,7 @@ import django
from django.conf import settings from django.conf import settings
# Force settings to run so that the python path is modified # Force settings to run so that the python path is modified
settings.INSTALLED_APPS # pylint: disable=pointless-statement settings.INSTALLED_APPS # pylint: disable=pointless-statement
from openedx.core.lib.django_startup import autostartup from openedx.core.lib.django_startup import autostartup
...@@ -20,6 +21,7 @@ from monkey_patch import ( ...@@ -20,6 +21,7 @@ from monkey_patch import (
import xmodule.x_module import xmodule.x_module
import lms_xblock.runtime import lms_xblock.runtime
from startup_configurations.validate_config import validate_lms_config
from openedx.core.djangoapps.theming.core import enable_theming from openedx.core.djangoapps.theming.core import enable_theming
from openedx.core.djangoapps.theming.helpers import is_comprehensive_theming_enabled from openedx.core.djangoapps.theming.helpers import is_comprehensive_theming_enabled
...@@ -82,6 +84,9 @@ def run(): ...@@ -82,6 +84,9 @@ def run():
xmodule.x_module.descriptor_global_handler_url = lms_xblock.runtime.handler_url xmodule.x_module.descriptor_global_handler_url = lms_xblock.runtime.handler_url
xmodule.x_module.descriptor_global_local_resource_url = lms_xblock.runtime.local_resource_url xmodule.x_module.descriptor_global_local_resource_url = lms_xblock.runtime.local_resource_url
# validate configurations on startup
validate_lms_config(settings)
def add_mimetypes(): def add_mimetypes():
""" """
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment