Commit 175f59b4 by Adam Palay Committed by Giulio Gratta

fixes Edit Course In Studio link on instr dash (LMS-1455)

add DOC_STORE_CONFIG to test settings

Conflicts:
	lms/djangoapps/courseware/courses.py
	lms/djangoapps/courseware/tests/test_courses.py
	lms/djangoapps/instructor/views/instructor_dashboard.py
parent debbed56
...@@ -10,7 +10,7 @@ from django.conf import settings ...@@ -10,7 +10,7 @@ from django.conf import settings
from .module_render import get_module from .module_render import get_module
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from xmodule.modulestore import Location, XML_MODULESTORE_TYPE from xmodule.modulestore import Location, XML_MODULESTORE_TYPE
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore, loc_mapper
from xmodule.contentstore.content import StaticContent from xmodule.contentstore.content import StaticContent
from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError from xmodule.modulestore.exceptions import ItemNotFoundError, InvalidLocationError
from courseware.model_data import FieldDataCache from courseware.model_data import FieldDataCache
...@@ -315,29 +315,24 @@ def sort_by_announcement(courses): ...@@ -315,29 +315,24 @@ def sort_by_announcement(courses):
return courses return courses
def registered_for_course(course, user): def registered_for_course(course, user):
""" """
Return CourseEnrollment if user is registered for course, else False Return CourseEnrollment if user is registered for course, else False
""" """
if user is None: if user is None:
return False return False
if user.is_authenticated(): if user.is_authenticated():
return CourseEnrollment.is_enrolled(user, course.id) return CourseEnrollment.is_enrolled(user, course.id)
else: else:
return False return False
def get_cms_course_link(course):
def get_cms_course_link_by_id(course_id):
""" """
Returns a proto-relative link to course_index for editing the course in cms, assuming that the course is actually Returns a link to course_index for editing the course in cms,
cms-backed. If course_id is improperly formatted, just return the root of the cms assuming that the course is actually cms-backed.
""" """
format_str = r'^(?P<org>[^/]+)/(?P<course>[^/]+)/(?P<name>[^/]+)$' locator = loc_mapper().translate_location(
host = "//{}/".format(settings.CMS_BASE) # protocol-relative course.location.course_id, course.location, False, True
m_obj = re.match(format_str, course_id) )
if m_obj: return "//" + settings.CMS_BASE + locator.url_reverse('course/', '')
return "{host}{org}/{course}/course/{name}".format(host=host,
org=m_obj.group('org'),
course=m_obj.group('course'),
name=m_obj.group('name'))
return host
...@@ -6,8 +6,8 @@ import datetime ...@@ -6,8 +6,8 @@ import datetime
from mock import MagicMock from mock import MagicMock
import mock import mock
from django.test import TestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from django.conf import settings
from django.http import Http404 from django.http import Http404
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.test.client import RequestFactory from django.test.client import RequestFactory
...@@ -17,61 +17,16 @@ from xmodule.modulestore.django import modulestore ...@@ -17,61 +17,16 @@ from xmodule.modulestore.django import modulestore
import courseware.views as views import courseware.views as views
from django.test.utils import override_settings from django.test.utils import override_settings
from courseware.courses import get_course_by_id, get_course, get_cms_course_link_by_id from courseware.courses import get_course_by_id, get_course, get_cms_course_link
from xmodule.modulestore.django import get_default_store_name_for_current_request from xmodule.modulestore.django import get_default_store_name_for_current_request
from xmodule.modulestore.tests.factories import CourseFactory
CMS_BASE_TEST = 'testcms' from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
class Stub():
pass
# This part is required for modulestore() to work properly CMS_BASE_TEST = 'testcms'
def xml_store_config(data_dir):
return {
'default': {
'ENGINE': 'xmodule.modulestore.xml.XMLModuleStore',
'OPTIONS': {
'data_dir': data_dir,
'default_class': 'xmodule.hidden_module.HiddenDescriptor',
}
}
}
TEST_DATA_DIR = settings.COMMON_TEST_DATA_ROOT
TEST_DATA_XML_MODULESTORE = xml_store_config(TEST_DATA_DIR)
class CoursesTestCase(TestCase):
def setUp(self):
self.user = User.objects.create(username='dummy', password='123456',
email='test@mit.edu')
self.date = datetime.datetime(2013, 1, 22, tzinfo=UTC)
self.course_id = 'edX/toy/2012_Fall'
self.enrollment = CourseEnrollment.objects.get_or_create(user=self.user,
course_id=self.course_id,
created=self.date)[0]
self.location = ['tag', 'org', 'course', 'category', 'name']
self._MODULESTORES = {}
# This is a CourseDescriptor object
self.toy_course = modulestore().get_course('edX/toy/2012_Fall')
self.request_factory = RequestFactory()
chapter = 'Overview'
self.chapter_url = '%s/%s/%s' % ('/courses', self.course_id, chapter)
def test_registered_for_course(self): class CoursesTest(ModuleStoreTestCase):
self.assertFalse(views.registered_for_course('Basketweaving', None))
mock_user = MagicMock()
mock_user.is_authenticated.return_value = False
self.assertFalse(views.registered_for_course('dummy', mock_user))
mock_course = MagicMock()
mock_course.id = self.course_id
self.assertTrue(views.registered_for_course(mock_course, self.user))
=======
>>>>>>> origin/release
class CoursesTest(TestCase):
"""Test methods related to fetching courses.""" """Test methods related to fetching courses."""
def test_get_course_by_id_invalid_chars(self): def test_get_course_by_id_invalid_chars(self):
...@@ -96,21 +51,41 @@ class CoursesTest(TestCase): ...@@ -96,21 +51,41 @@ class CoursesTest(TestCase):
get_course('MITx/foobar/business and management') get_course('MITx/foobar/business and management')
get_course('MITx/foobar/NiñøJoséMaríáßç') get_course('MITx/foobar/NiñøJoséMaríáßç')
@override_settings(CMS_BASE=CMS_BASE_TEST) @override_settings(
def test_get_cms_course_link_by_id(self): MODULESTORE=TEST_DATA_MONGO_MODULESTORE, CMS_BASE=CMS_BASE_TEST
)
def test_get_cms_course_link(self):
""" """
Tests that get_cms_course_link_by_id returns the right thing Tests that get_cms_course_link_by_id returns the right thing
""" """
self.assertEqual("//{}/".format(CMS_BASE_TEST), get_cms_course_link_by_id("blah_bad_course_id"))
self.assertEqual("//{}/".format(CMS_BASE_TEST), get_cms_course_link_by_id("too/too/many/slashes"))
self.assertEqual("//{}/org/num/course/name".format(CMS_BASE_TEST), get_cms_course_link_by_id('org/num/name'))
@mock.patch('xmodule.modulestore.django.get_current_request_hostname', mock.Mock(return_value='preview.localhost')) self.course = CourseFactory.create(
@override_settings(HOSTNAME_MODULESTORE_DEFAULT_MAPPINGS={r'preview\.': 'draft'}) org='org', number='num', display_name='name'
)
self.assertEqual(
u"//{}/course/org.num.name/branch/draft/block/name".format(
CMS_BASE_TEST
),
get_cms_course_link(self.course)
)
@mock.patch(
'xmodule.modulestore.django.get_current_request_hostname',
mock.Mock(return_value='preview.localhost')
)
@override_settings(
HOSTNAME_MODULESTORE_DEFAULT_MAPPINGS={r'preview\.': 'draft'}
)
def test_default_modulestore_preview_mapping(self): def test_default_modulestore_preview_mapping(self):
self.assertEqual(get_default_store_name_for_current_request(), 'draft') self.assertEqual(get_default_store_name_for_current_request(), 'draft')
@mock.patch('xmodule.modulestore.django.get_current_request_hostname', mock.Mock(return_value='localhost')) @mock.patch(
@override_settings(HOSTNAME_MODULESTORE_DEFAULT_MAPPINGS={r'preview\.': 'draft'}) 'xmodule.modulestore.django.get_current_request_hostname',
mock.Mock(return_value='localhost')
)
@override_settings(
HOSTNAME_MODULESTORE_DEFAULT_MAPPINGS={r'preview\.': 'draft'}
)
def test_default_modulestore_published_mapping(self): def test_default_modulestore_published_mapping(self):
self.assertEqual(get_default_store_name_for_current_request(), 'default') self.assertEqual(get_default_store_name_for_current_request(), 'default')
...@@ -18,7 +18,9 @@ from xmodule.modulestore.django import modulestore ...@@ -18,7 +18,9 @@ from xmodule.modulestore.django import modulestore
from xblock.field_data import DictFieldData from xblock.field_data import DictFieldData
from xblock.fields import ScopeIds from xblock.fields import ScopeIds
from courseware.access import has_access from courseware.access import has_access
from courseware.courses import get_course_by_id
from courseware.courses import get_course_by_id, get_cms_course_link
from django_comment_client.utils import has_forum_access from django_comment_client.utils import has_forum_access
from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR from django_comment_common.models import FORUM_ROLE_ADMINISTRATOR
from student.models import CourseEnrollment from student.models import CourseEnrollment
...@@ -52,6 +54,15 @@ def instructor_dashboard_2(request, course_id): ...@@ -52,6 +54,15 @@ def instructor_dashboard_2(request, course_id):
_section_analytics(course_id), _section_analytics(course_id),
] ]
# Gate access to course email by feature flag & by course-specific authorization
if settings.MITX_FEATURES['ENABLE_INSTRUCTOR_EMAIL'] and \
is_studio_course and CourseAuthorization.instructor_email_enabled(course_id):
sections.append(_section_send_email(course_id, access, course))
studio_url = None
if is_studio_course:
studio_url = get_cms_course_link(course)
enrollment_count = sections[0]['enrollment_count'] enrollment_count = sections[0]['enrollment_count']
disable_buttons = False disable_buttons = False
max_enrollment_for_buttons = settings.MITX_FEATURES.get("MAX_ENROLLMENT_INSTR_BUTTONS") max_enrollment_for_buttons = settings.MITX_FEATURES.get("MAX_ENROLLMENT_INSTR_BUTTONS")
......
...@@ -34,7 +34,7 @@ from bulk_email.models import CourseEmail, CourseAuthorization ...@@ -34,7 +34,7 @@ from bulk_email.models import CourseEmail, CourseAuthorization
from courseware import grades from courseware import grades
from courseware.access import (has_access, get_access_group_name, from courseware.access import (has_access, get_access_group_name,
course_beta_test_group_name) course_beta_test_group_name)
from courseware.courses import get_course_with_access, get_cms_course_link_by_id from courseware.courses import get_course_with_access, get_cms_course_link
from courseware.models import StudentModule from courseware.models import StudentModule
from django_comment_common.models import (Role, from django_comment_common.models import (Role,
FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_ADMINISTRATOR,
...@@ -484,7 +484,7 @@ def instructor_dashboard(request, course_id): ...@@ -484,7 +484,7 @@ def instructor_dashboard(request, course_id):
except IndexError: except IndexError:
log.debug('No grade for assignment %s (%s) for student %s' % (aidx, aname, x.email)) log.debug('No grade for assignment %s (%s) for student %s' % (aidx, aname, x.email))
datatable['data'] = ddata datatable['data'] = ddata
datatable['title'] = 'Grades for assignment "%s"' % aname datatable['title'] = 'Grades for assignment "%s"' % aname
if 'Export CSV' in action: if 'Export CSV' in action:
...@@ -843,7 +843,7 @@ def instructor_dashboard(request, course_id): ...@@ -843,7 +843,7 @@ def instructor_dashboard(request, course_id):
studio_url = None studio_url = None
if is_studio_course: if is_studio_course:
studio_url = get_cms_course_link_by_id(course_id) studio_url = get_cms_course_link(course)
email_editor = None email_editor = None
# HTML editor for email # HTML editor for email
......
...@@ -121,6 +121,12 @@ CONTENTSTORE = { ...@@ -121,6 +121,12 @@ CONTENTSTORE = {
} }
} }
DOC_STORE_CONFIG = {
'host': 'localhost',
'db': 'test_xmodule',
'collection': 'test_modulestore',
}
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.sqlite3',
......
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