Commit 4ca5012f by Don Mitchell

Use split to test views

parent d43d5d7d
"""
Script for finding all courses whose org/name pairs == other courses when ignoring case
"""
from django.core.management.base import BaseCommand
from xmodule.modulestore.django import modulestore
from xmodule.modulestore import ModuleStoreEnum
#
# To run from command line: ./manage.py cms --settings dev course_id_clash
#
class Command(BaseCommand):
"""
Script for finding all courses in the Mongo Modulestore whose org/name pairs == other courses when ignoring case
"""
help = 'List all courses ids in the Mongo Modulestore which may collide when ignoring case'
def handle(self, *args, **options):
mstore = modulestore()._get_modulestore_by_type(ModuleStoreEnum.Type.mongo) # pylint: disable=protected-access
if hasattr(mstore, 'collection'):
map_fn = '''
function () {
emit(this._id.org.toLowerCase()+this._id.course.toLowerCase(), {target: this._id});
}
'''
reduce_fn = '''
function (idpair, matches) {
var result = {target: []};
matches.forEach(function (match) {
result.target.push(match.target);
});
return result;
}
'''
finalize = '''
function(key, reduced) {
if (Array.isArray(reduced.target)) {
return reduced;
}
else {return null;}
}
'''
results = mstore.collection.map_reduce(
map_fn, reduce_fn, {'inline': True}, query={'_id.category': 'course'}, finalize=finalize
)
results = results.get('results')
for entry in results:
if entry.get('value') is not None:
print '{:-^40}'.format(entry.get('_id'))
for course_id in entry.get('value').get('target'):
print ' {}/{}/{}'.format(course_id.get('org'), course_id.get('course'), course_id.get('name'))
import sys
from StringIO import StringIO
from django.test import TestCase
from django.core.management import call_command
from xmodule.modulestore.tests.factories import CourseFactory
class ClashIdTestCase(TestCase):
"""
Test for course_id_clash.
"""
def test_course_clash(self):
"""
Test for course_id_clash.
"""
expected = []
# clashing courses
course = CourseFactory.create(org="test", course="courseid", display_name="run1")
expected.append(course.id)
course = CourseFactory.create(org="TEST", course="courseid", display_name="RUN12")
expected.append(course.id)
course = CourseFactory.create(org="test", course="CourseId", display_name="aRUN123")
expected.append(course.id)
# not clashing courses
not_expected = []
course = CourseFactory.create(org="test", course="course2", display_name="run1")
not_expected.append(course.id)
course = CourseFactory.create(org="test1", course="courseid", display_name="run1")
not_expected.append(course.id)
course = CourseFactory.create(org="test", course="courseid0", display_name="run1")
not_expected.append(course.id)
old_stdout = sys.stdout
sys.stdout = mystdout = StringIO()
call_command('course_id_clash', stdout=mystdout)
sys.stdout = old_stdout
result = mystdout.getvalue()
for courseid in expected:
self.assertIn(courseid.to_deprecated_string(), result)
for courseid in not_expected:
self.assertNotIn(courseid.to_deprecated_string(), result)
......@@ -49,8 +49,6 @@ from opaque_keys import InvalidKeyError
from contentstore.tests.utils import get_url
from course_action_state.models import CourseRerunState, CourseRerunUIStateManager
from unittest import skipIf
from course_action_state.managers import CourseActionStateItemNotFoundError
......@@ -63,7 +61,7 @@ class ContentStoreTestCase(CourseTestCase):
"""
Base class for Content Store Test Cases
"""
pass
class ContentStoreToyCourseTest(ContentStoreTestCase):
"""
......@@ -317,7 +315,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
def test_delete(self):
store = self.store
course = CourseFactory.create(org='edX', course='999', display_name='Robot Super Course')
course = CourseFactory.create()
chapterloc = ItemFactory.create(parent_location=course.location, display_name="Chapter").location
ItemFactory.create(parent_location=chapterloc, category='sequential', display_name="Sequential")
......@@ -567,7 +565,7 @@ class ContentStoreToyCourseTest(ContentStoreTestCase):
def test_illegal_draft_crud_ops(self):
draft_store = self.store
course = CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course')
course = CourseFactory.create()
location = course.id.make_usage_key('chapter', 'neuvo')
# Ensure draft mongo store does not create drafts for things that shouldn't be draft
......@@ -1186,7 +1184,7 @@ class ContentStoreTest(ContentStoreTestCase):
def test_course_index_view_with_course(self):
"""Test viewing the index page with an existing course"""
CourseFactory.create(display_name='Robot Super Educational Course')
CourseFactory.create(, display_name='Robot Super Educational Course')
resp = self.client.get_html('/course/')
self.assertContains(
resp,
......@@ -1197,13 +1195,14 @@ class ContentStoreTest(ContentStoreTestCase):
def test_course_overview_view_with_course(self):
"""Test viewing the course overview page with an existing course"""
course = CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course')
course_cat_num = self.random_course_name()
course = CourseFactory.create(org='MITx', course=course_cat_num, display_name='Robot Super Course')
resp = self._show_course_overview(course.id)
self.assertContains(
resp,
'<article class="outline outline-complex outline-course" data-locator="{locator}" data-course-key="{course_key}">'.format(
locator='i4x://MITx/999/course/Robot_Super_Course',
course_key='MITx/999/Robot_Super_Course',
locator=unicode(course.location),
course_key=unicode(course.id),
),
status_code=200,
html=True
......@@ -1211,7 +1210,7 @@ class ContentStoreTest(ContentStoreTestCase):
def test_create_item(self):
"""Test creating a new xblock instance."""
course = _course_factory_create_course()
course = CourseFactory.create()()
section_data = {
'parent_locator': unicode(course.location),
......@@ -1223,14 +1222,12 @@ class ContentStoreTest(ContentStoreTestCase):
self.assertEqual(resp.status_code, 200)
data = parse_json(resp)
self.assertRegexpMatches(
data['locator'],
r"MITx/999/chapter/([0-9]|[a-f]){3,}$"
)
retarget = unicode(course.id.make_usage_key('chapter', 'REPLACE')).replace('REPLACE', r'([0-9]|[a-f]){3,}')
self.assertRegexpMatches(data['locator'], retarget)
def test_capa_module(self):
"""Test that a problem treats markdown specially."""
course = _course_factory_create_course()
course = CourseFactory.create()()
problem_data = {
'parent_locator': unicode(course.location),
......@@ -1382,7 +1379,7 @@ class ContentStoreTest(ContentStoreTestCase):
self.assertTrue(did_load_item)
def test_forum_id_generation(self):
course = CourseFactory.create(org='edX', course='999', display_name='Robot Super Course')
course = CourseFactory.create()
# crate a new module and add it as a child to a vertical
new_discussion_item = self.store.create_item(self.user.id, course.id, 'discussion', 'new_component')
......@@ -1501,8 +1498,7 @@ class MetadataSaveTestCase(ContentStoreTestCase):
def setUp(self):
super(MetadataSaveTestCase, self).setUp()
course = CourseFactory.create(
org='edX', course='999', display_name='Robot Super Course')
course = CourseFactory.create()
video_sample_xml = '''
<video display_name="Test Video"
......@@ -1640,7 +1636,6 @@ class RerunCourseTest(ContentStoreTestCase):
self.assertInCourseListing(source_course_key)
self.assertInCourseListing(destination_course_key)
def test_rerun_course_success(self):
source_course = CourseFactory.create()
destination_course_key = self.post_rerun_request(source_course.id)
......@@ -1755,13 +1750,6 @@ def _create_course(test, course_key, course_data):
test.assertEqual(data['url'], course_url)
def _course_factory_create_course():
"""
Creates a course via the CourseFactory and returns the locator for it.
"""
return CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course')
def _get_course_id(course_data, key_class=SlashSeparatedCourseKey):
"""Returns the course ID (org/number/run)."""
return key_class(course_data['org'], course_data['number'], course_data['run'])
......@@ -210,57 +210,6 @@ class TestCourseListing(ModuleStoreTestCase):
with check_mongo_calls(3):
_accessible_courses_list(self.request)
def test_get_course_list_with_same_course_id(self):
"""
Test getting courses with same id but with different name case. Then try to delete one of them and
check that it is properly deleted and other one is accessible
"""
course_location_caps = SlashSeparatedCourseKey('Org', 'COURSE', 'Run')
self._create_course_with_access_groups(course_location_caps, self.user)
# get courses through iterating all courses
courses_list, __ = _accessible_courses_list(self.request)
self.assertEqual(len(courses_list), 1)
# get courses by reversing group name formats
courses_list_by_groups, __ = _accessible_courses_list_from_groups(self.request)
self.assertEqual(len(courses_list_by_groups), 1)
# check both course lists have same courses
self.assertEqual(courses_list, courses_list_by_groups)
# now create another course with same course_id but different name case
course_location_camel = SlashSeparatedCourseKey('Org', 'Course', 'Run')
self._create_course_with_access_groups(course_location_camel, self.user)
# test that get courses through iterating all courses returns both courses
courses_list, __ = _accessible_courses_list(self.request)
self.assertEqual(len(courses_list), 2)
# test that get courses by reversing group name formats returns both courses
courses_list_by_groups, __ = _accessible_courses_list_from_groups(self.request)
self.assertEqual(len(courses_list_by_groups), 2)
# now delete first course (course_location_caps) and check that it is no longer accessible
delete_course_and_groups(course_location_caps, self.user.id)
# test that get courses through iterating all courses now returns one course
courses_list, __ = _accessible_courses_list(self.request)
self.assertEqual(len(courses_list), 1)
# test that get courses by reversing group name formats also returns one course
courses_list_by_groups, __ = _accessible_courses_list_from_groups(self.request)
self.assertEqual(len(courses_list_by_groups), 1)
# now check that deleted course is not accessible
outline_url = reverse_course_url('course_handler', course_location_caps)
response = self.client.get(outline_url, HTTP_ACCEPT='application/json')
self.assertEqual(response.status_code, 403)
# now check that other course is accessible
outline_url = reverse_course_url('course_handler', course_location_camel)
response = self.client.get(outline_url, HTTP_ACCEPT='application/json')
self.assertEqual(response.status_code, 200)
def test_course_listing_errored_deleted_courses(self):
"""
Create good courses, courses that won't load, and deleted courses which still have
......
......@@ -441,19 +441,19 @@ class CourseMetadataEditingTest(CourseTestCase):
"""
def setUp(self):
CourseTestCase.setUp(self)
self.fullcourse = CourseFactory.create(org='edX', course='999', display_name='Robot Super Course')
self.fullcourse = CourseFactory.create()
self.course_setting_url = get_url(self.course.id, 'advanced_settings_handler')
self.fullcourse_setting_url = get_url(self.fullcourse.id, 'advanced_settings_handler')
def test_fetch_initial_fields(self):
test_model = CourseMetadata.fetch(self.course)
self.assertIn('display_name', test_model, 'Missing editable metadata field')
self.assertEqual(test_model['display_name']['value'], 'Robot Super Course', "not expected value")
self.assertEqual(test_model['display_name']['value'], self.course.display_name)
test_model = CourseMetadata.fetch(self.fullcourse)
self.assertNotIn('graceperiod', test_model, 'blacklisted field leaked in')
self.assertIn('display_name', test_model, 'full missing editable metadata field')
self.assertEqual(test_model['display_name']['value'], 'Robot Super Course', "not expected value")
self.assertEqual(test_model['display_name']['value'], self.fullcourse.display_name)
self.assertIn('rerandomize', test_model, 'Missing rerandomize metadata field')
self.assertIn('showanswer', test_model, 'showanswer field ')
self.assertIn('xqa_key', test_model, 'xqa_key field ')
......@@ -554,7 +554,7 @@ class CourseMetadataEditingTest(CourseTestCase):
checks that updates were made
"""
self.assertIn('display_name', test_model, 'Missing editable metadata field')
self.assertEqual(test_model['display_name']['value'], 'Robot Super Course', "not expected value")
self.assertEqual(test_model['display_name']['value'], self.course.display_name)
self.assertIn('advertised_start', test_model, 'Missing new advertised_start metadata field')
self.assertEqual(test_model['advertised_start']['value'], 'start A', "advertised_start not expected value")
self.assertIn('days_early_for_beta', test_model, 'Missing days_early_for_beta metadata field')
......@@ -564,13 +564,13 @@ class CourseMetadataEditingTest(CourseTestCase):
response = self.client.get_json(self.course_setting_url)
test_model = json.loads(response.content)
self.assertIn('display_name', test_model, 'Missing editable metadata field')
self.assertEqual(test_model['display_name']['value'], 'Robot Super Course', "not expected value")
self.assertEqual(test_model['display_name']['value'], self.course.display_name)
response = self.client.get_json(self.fullcourse_setting_url)
test_model = json.loads(response.content)
self.assertNotIn('graceperiod', test_model, 'blacklisted field leaked in')
self.assertIn('display_name', test_model, 'full missing editable metadata field')
self.assertEqual(test_model['display_name']['value'], 'Robot Super Course', "not expected value")
self.assertEqual(test_model['display_name']['value'], self.fullcourse.display_name)
self.assertIn('rerandomize', test_model, 'Missing rerandomize metadata field')
self.assertIn('showanswer', test_model, 'showanswer field ')
self.assertIn('xqa_key', test_model, 'xqa_key field ')
......
......@@ -12,7 +12,7 @@ from contentstore import utils
from contentstore.tests.utils import CourseTestCase
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
from opaque_keys.edx.locations import SlashSeparatedCourseKey, Location
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.django import modulestore
from opaque_keys.edx.locator import CourseLocator
......@@ -168,27 +168,26 @@ class CourseImageTestCase(TestCase):
def test_get_image_url(self):
"""Test image URL formatting."""
course = CourseFactory.create(org='edX', course='999')
course = CourseFactory.create()
url = utils.course_image_url(course)
self.assertEquals(url, '/c4x/edX/999/asset/{0}'.format(course.course_image))
self.assertEquals(url, unicode(course.id.make_asset_key('asset', course.course_image)))
def test_non_ascii_image_name(self):
# Verify that non-ascii image names are cleaned
course = CourseFactory.create(course_image=u'before_\N{SNOWMAN}_after.jpg')
""" Verify that non-ascii image names are cleaned """
course_image = u'before_\N{SNOWMAN}_after.jpg'
course = CourseFactory.create(course_image=course_image)
self.assertEquals(
utils.course_image_url(course),
'/c4x/{org}/{course}/asset/before___after.jpg'.format(org=course.location.org, course=course.location.course)
unicode(course.id.make_asset_key('asset', course_image.replace(u'\N{SNOWMAN}', '_')))
)
def test_spaces_in_image_name(self):
# Verify that image names with spaces in them are cleaned
""" Verify that image names with spaces in them are cleaned """
course_image = u'before after.jpg'
course = CourseFactory.create(course_image=u'before after.jpg')
self.assertEquals(
utils.course_image_url(course),
'/c4x/{org}/{course}/asset/before_after.jpg'.format(
org=course.location.org,
course=course.location.course
)
unicode(course.id.make_asset_key('asset', course_image.replace(" ", "_")))
)
......
......@@ -77,11 +77,7 @@ class CourseTestCase(ModuleStoreTestCase):
self.client = AjaxEnabledTestClient()
self.client.login(username=self.user.username, password=user_password)
self.course = CourseFactory.create(
org='MITx',
number='999',
display_name='Robot Super Course',
)
self.course = CourseFactory.create()
def create_non_staff_authed_user_client(self, authenticate=True):
"""
......
......@@ -8,6 +8,7 @@ from pytz import UTC
from contentstore.views.tests.utils import StudioPageTestCase
from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.factories import ItemFactory
from django.utils import http
class ContainerPageTestCase(StudioPageTestCase):
......@@ -59,8 +60,8 @@ class ContainerPageTestCase(StudioPageTestCase):
course=re.escape(unicode(self.course.id)),
unit=re.escape(unicode(self.vertical.location)),
classes='navigation-item navigation-link navigation-parent',
section_parameters=re.escape(u'?show=i4x%3A//MITx/999/chapter/Week_1'),
subsection_parameters=re.escape(u'?show=i4x%3A//MITx/999/sequential/Lesson_1'),
section_parameters=re.escape(u'?show={}'.format(http.urlquote(self.chapter.location))),
subsection_parameters=re.escape(u'?show={}'.format(http.urlquote(self.sequential.location))),
),
)
......@@ -89,8 +90,8 @@ class ContainerPageTestCase(StudioPageTestCase):
unit=re.escape(unicode(self.vertical.location)),
split_test=re.escape(unicode(self.child_container.location)),
classes='navigation-item navigation-link navigation-parent',
section_parameters=re.escape(u'?show=i4x%3A//MITx/999/chapter/Week_1'),
subsection_parameters=re.escape(u'?show=i4x%3A//MITx/999/sequential/Lesson_1'),
section_parameters=re.escape(u'?show={}'.format(http.urlquote(self.chapter.location))),
subsection_parameters=re.escape(u'?show={}'.format(http.urlquote(self.sequential.location))),
),
)
......
......@@ -106,8 +106,8 @@ class TestCourseIndex(CourseTestCase):
# First spot check some values in the root response
self.assertEqual(json_response['category'], 'course')
self.assertEqual(json_response['id'], 'i4x://MITx/999/course/Robot_Super_Course')
self.assertEqual(json_response['display_name'], 'Robot Super Course')
self.assertEqual(json_response['id'], unicode(self.course.location))
self.assertEqual(json_response['display_name'], self.course.display_name)
self.assertTrue(json_response['published'])
self.assertIsNone(json_response['visibility_state'])
......@@ -116,7 +116,7 @@ class TestCourseIndex(CourseTestCase):
self.assertTrue(len(children) > 0)
first_child_response = children[0]
self.assertEqual(first_child_response['category'], 'chapter')
self.assertEqual(first_child_response['id'], 'i4x://MITx/999/chapter/Week_1')
self.assertEqual(first_child_response['id'], unicode(chapter.location))
self.assertEqual(first_child_response['display_name'], 'Week 1')
self.assertTrue(json_response['published'])
self.assertEqual(first_child_response['visibility_state'], VisibilityState.unscheduled)
......@@ -227,8 +227,8 @@ class TestCourseOutline(CourseTestCase):
# First spot check some values in the root response
self.assertEqual(json_response['category'], 'course')
self.assertEqual(json_response['id'], 'i4x://MITx/999/course/Robot_Super_Course')
self.assertEqual(json_response['display_name'], 'Robot Super Course')
self.assertEqual(json_response['id'], unicode(self.course.location))
self.assertEqual(json_response['display_name'], self.course.display_name)
self.assertTrue(json_response['published'])
self.assertIsNone(json_response['visibility_state'])
......@@ -237,7 +237,7 @@ class TestCourseOutline(CourseTestCase):
self.assertTrue(len(children) > 0)
first_child_response = children[0]
self.assertEqual(first_child_response['category'], 'chapter')
self.assertEqual(first_child_response['id'], 'i4x://MITx/999/chapter/Week_1')
self.assertEqual(first_child_response['id'], unicode(self.chapter.location))
self.assertEqual(first_child_response['display_name'], 'Week 1')
self.assertTrue(json_response['published'])
self.assertEqual(first_child_response['visibility_state'], VisibilityState.unscheduled)
......
......@@ -10,6 +10,8 @@ from contentstore.tests.utils import CourseTestCase
from xmodule.partitions.partitions import Group, UserPartition
from xmodule.modulestore.tests.factories import ItemFactory
from xmodule.split_test_module import ValidationMessage, ValidationMessageType
from xmodule.modulestore.django import modulestore
from xmodule.modulestore import ModuleStoreEnum
GROUP_CONFIGURATION_JSON = {
u'name': u'Test name',
......@@ -266,12 +268,6 @@ class GroupConfigurationsDetailHandlerTestCase(CourseTestCase, GroupConfiguratio
ID = 0
def setUp(self):
"""
Set up GroupConfigurationsDetailHandlerTestCase.
"""
super(GroupConfigurationsDetailHandlerTestCase, self).setUp()
def _url(self, cid=-1):
"""
Return url for the handler.
......@@ -450,7 +446,7 @@ class GroupConfigurationsUsageInfoTestCase(CourseTestCase, HelperMethods):
Test if group configurations json updated successfully with usage information.
"""
self._add_user_partitions(count=2)
self._create_content_experiment(cid=0, name_suffix='0')
vertical, __ = self._create_content_experiment(cid=0, name_suffix='0')
self._create_content_experiment(name_suffix='1')
actual = GroupConfiguration.add_usage_info(self.course, self.store)
......@@ -466,7 +462,7 @@ class GroupConfigurationsUsageInfoTestCase(CourseTestCase, HelperMethods):
{'id': 2, 'name': 'Group C', 'version': 1},
],
'usage': [{
'url': '/container/i4x://MITx/999/vertical/Test_Unit_0',
'url': '/container/{}'.format(vertical.location),
'label': 'Test Unit 0 / Test Content Experiment 0',
'validation': None,
}],
......@@ -491,8 +487,8 @@ class GroupConfigurationsUsageInfoTestCase(CourseTestCase, HelperMethods):
group configuration.
"""
self._add_user_partitions()
self._create_content_experiment(cid=0, name_suffix='0')
self._create_content_experiment(cid=0, name_suffix='1')
vertical, __ = self._create_content_experiment(cid=0, name_suffix='0')
vertical1, __ = self._create_content_experiment(cid=0, name_suffix='1')
actual = GroupConfiguration.add_usage_info(self.course, self.store)
......@@ -507,11 +503,11 @@ class GroupConfigurationsUsageInfoTestCase(CourseTestCase, HelperMethods):
{'id': 2, 'name': 'Group C', 'version': 1},
],
'usage': [{
'url': '/container/i4x://MITx/999/vertical/Test_Unit_0',
'url': '/container/{}'.format(vertical.location),
'label': 'Test Unit 0 / Test Content Experiment 0',
'validation': None,
}, {
'url': '/container/i4x://MITx/999/vertical/Test_Unit_1',
'url': '/container/{}'.format(vertical1.location),
'label': 'Test Unit 1 / Test Content Experiment 1',
'validation': None,
}],
......@@ -524,11 +520,15 @@ class GroupConfigurationsUsageInfoTestCase(CourseTestCase, HelperMethods):
"""
self._add_user_partitions()
# Create split test without parent.
ItemFactory.create(
category='split_test',
user_partition_id=0,
display_name='Test Content Experiment'
)
with modulestore().branch_setting(ModuleStoreEnum.Branch.published_only):
orphan = modulestore().create_item(
ModuleStoreEnum.UserID.test,
self.course.id, 'split_test',
)
orphan.user_partition_id = 0
orphan.display_name = 'Test Content Experiment'
modulestore().update_item(orphan, ModuleStoreEnum.UserID.test)
self.save_course()
actual = GroupConfiguration.get_usage_info(self.course, self.store)
self.assertEqual(actual, {0: []})
......
......@@ -5,6 +5,7 @@ Unit tests for helpers.py.
from contentstore.tests.utils import CourseTestCase
from contentstore.views.helpers import xblock_studio_url, xblock_type_display_name
from xmodule.modulestore.tests.factories import ItemFactory
from django.utils import http
class HelpersTestCase(CourseTestCase):
......@@ -15,36 +16,34 @@ class HelpersTestCase(CourseTestCase):
def test_xblock_studio_url(self):
# Verify course URL
self.assertEqual(xblock_studio_url(self.course),
u'/course/MITx/999/Robot_Super_Course')
course_url = u'/course/{}'.format(unicode(self.course.id))
self.assertEqual(xblock_studio_url(self.course), course_url)
# Verify chapter URL
chapter = ItemFactory.create(parent_location=self.course.location, category='chapter',
display_name="Week 1")
self.assertEqual(xblock_studio_url(chapter),
u'/course/MITx/999/Robot_Super_Course?show={escaped_usage_key}'.format(
escaped_usage_key='i4x%3A//MITx/999/chapter/Week_1'
))
self.assertEqual(
xblock_studio_url(chapter),
u'{}?show={}'.format(course_url, http.urlquote(chapter.location))
)
# Verify sequential URL
sequential = ItemFactory.create(parent_location=chapter.location, category='sequential',
display_name="Lesson 1")
self.assertEqual(xblock_studio_url(sequential),
u'/course/MITx/999/Robot_Super_Course?show={escaped_usage_key}'.format(
escaped_usage_key='i4x%3A//MITx/999/sequential/Lesson_1'
))
self.assertEqual(
xblock_studio_url(sequential),
u'{}?show={}'.format(course_url, http.urlquote(sequential.location))
)
# Verify unit URL
vertical = ItemFactory.create(parent_location=sequential.location, category='vertical',
display_name='Unit')
self.assertEqual(xblock_studio_url(vertical),
u'/container/i4x://MITx/999/vertical/Unit')
self.assertEqual(xblock_studio_url(vertical), u'/container/{}'.format(vertical.location))
# Verify child vertical URL
child_vertical = ItemFactory.create(parent_location=vertical.location, category='vertical',
display_name='Child Vertical')
self.assertEqual(xblock_studio_url(child_vertical),
u'/container/i4x://MITx/999/vertical/Child_Vertical')
self.assertEqual(xblock_studio_url(child_vertical), u'/container/{}'.format(child_vertical.location))
# Verify video URL
video = ItemFactory.create(parent_location=child_vertical.location, category="video",
......
......@@ -293,7 +293,7 @@ class ExportTestCase(CourseTestCase):
"""
fake_xblock = ItemFactory.create(parent_location=self.course.location, category='aawefawef')
self.store.publish(fake_xblock.location, self.user.id)
self._verify_export_failure(u'/container/i4x://MITx/999/course/Robot_Super_Course')
self._verify_export_failure(u'/container/{}'.format(self.course.location))
def test_export_failure_subsection_level(self):
"""
......@@ -305,7 +305,7 @@ class ExportTestCase(CourseTestCase):
category='aawefawef'
)
self._verify_export_failure(u'/container/i4x://MITx/999/vertical/foo')
self._verify_export_failure(u'/container/{}'.format(vertical.location))
def _verify_export_failure(self, expectedText):
""" Export failure helper method. """
......
......@@ -177,8 +177,9 @@ class GetItemTest(ItemTest):
html,
# The instance of the wrapper class will have an auto-generated ID. Allow any
# characters after wrapper.
(r'"/container/i4x://MITx/999/wrapper/\w+" class="action-button">\s*'
'<span class="action-button-text">View</span>')
r'"/container/{}" class="action-button">\s*<span class="action-button-text">View</span>'.format(
wrapper_usage_key
)
)
def test_split_test(self):
......@@ -1269,8 +1270,8 @@ class TestXBlockInfo(ItemTest):
Validate that the xblock info is correct for the test course.
"""
self.assertEqual(xblock_info['category'], 'course')
self.assertEqual(xblock_info['id'], 'i4x://MITx/999/course/Robot_Super_Course')
self.assertEqual(xblock_info['display_name'], 'Robot Super Course')
self.assertEqual(xblock_info['id'], unicode(self.course.location))
self.assertEqual(xblock_info['display_name'], self.course.display_name)
self.assertTrue(xblock_info['published'])
# Finally, validate the entire response for consistency
......@@ -1281,7 +1282,7 @@ class TestXBlockInfo(ItemTest):
Validate that the xblock info is correct for the test chapter.
"""
self.assertEqual(xblock_info['category'], 'chapter')
self.assertEqual(xblock_info['id'], 'i4x://MITx/999/chapter/Week_1')
self.assertEqual(xblock_info['id'], unicode(self.chapter.location))
self.assertEqual(xblock_info['display_name'], 'Week 1')
self.assertTrue(xblock_info['published'])
self.assertIsNone(xblock_info.get('edited_by', None))
......@@ -1299,7 +1300,7 @@ class TestXBlockInfo(ItemTest):
Validate that the xblock info is correct for the test sequential.
"""
self.assertEqual(xblock_info['category'], 'sequential')
self.assertEqual(xblock_info['id'], 'i4x://MITx/999/sequential/Lesson_1')
self.assertEqual(xblock_info['id'], unicode(self.sequential.location))
self.assertEqual(xblock_info['display_name'], 'Lesson 1')
self.assertTrue(xblock_info['published'])
self.assertIsNone(xblock_info.get('edited_by', None))
......@@ -1312,7 +1313,7 @@ class TestXBlockInfo(ItemTest):
Validate that the xblock info is correct for the test vertical.
"""
self.assertEqual(xblock_info['category'], 'vertical')
self.assertEqual(xblock_info['id'], 'i4x://MITx/999/vertical/Unit_1')
self.assertEqual(xblock_info['id'], unicode(self.vertical.location))
self.assertEqual(xblock_info['display_name'], 'Unit 1')
self.assertTrue(xblock_info['published'])
self.assertEqual(xblock_info['edited_by'], 'testuser')
......@@ -1334,7 +1335,7 @@ class TestXBlockInfo(ItemTest):
Validate that the xblock info is correct for the test component.
"""
self.assertEqual(xblock_info['category'], 'video')
self.assertEqual(xblock_info['id'], 'i4x://MITx/999/video/My_Video')
self.assertEqual(xblock_info['id'], unicode(self.video.location))
self.assertEqual(xblock_info['display_name'], 'My Video')
self.assertTrue(xblock_info['published'])
self.assertIsNone(xblock_info.get('edited_by', None))
......
......@@ -45,8 +45,9 @@ class GetPreviewHtmlTestCase(TestCase):
html = get_preview_fragment(request, html, context).content
# Verify student view html is returned, and the usage ID is as expected.
html_pattern = unicode(course.id.make_usage_key('html', 'html_')).replace('html_', r'html_[0-9]*')
self.assertRegexpMatches(
html,
'data-usage-id="i4x://MITx/999/html/html_[0-9]*"'
'data-usage-id="{}"'.format(html_pattern)
)
self.assertRegexpMatches(html, '<html>foobar</html>')
......@@ -192,13 +192,12 @@ class TabsPageTests(CourseTestCase):
self.assertIn('<span data-tooltip="Drag to reorder" class="drag-handle action"></span>', html)
class PrimitiveTabEdit(TestCase):
"""Tests for the primitive tab edit data manipulations"""
def test_delete(self):
"""Test primitive tab deletion."""
course = CourseFactory.create(org='edX', course='999')
course = CourseFactory.create()
with self.assertRaises(ValueError):
tabs.primitive_delete(course, 0)
with self.assertRaises(ValueError):
......@@ -212,7 +211,7 @@ class PrimitiveTabEdit(TestCase):
def test_insert(self):
"""Test primitive tab insertion."""
course = CourseFactory.create(org='edX', course='999')
course = CourseFactory.create()
tabs.primitive_insert(course, 2, 'notes', 'aname')
self.assertEquals(course.tabs[2], {'type': 'notes', 'name': 'aname'})
with self.assertRaises(ValueError):
......@@ -222,7 +221,7 @@ class PrimitiveTabEdit(TestCase):
def test_save(self):
"""Test course saving."""
course = CourseFactory.create(org='edX', course='999')
course = CourseFactory.create()
tabs.primitive_insert(course, 3, 'notes', 'aname')
course2 = modulestore().get_course(course.id)
self.assertEquals(course2.tabs[3], {'type': 'notes', 'name': 'aname'})
......@@ -5,21 +5,22 @@ from datetime import timedelta, datetime
import pytz
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.test.utils import override_settings
from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
from reverification.models import MidcourseReverificationWindow
from reverification.tests.factories import MidcourseReverificationWindowFactory
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
class TestMidcourseReverificationWindow(TestCase):
class TestMidcourseReverificationWindow(ModuleStoreTestCase):
""" Tests for MidcourseReverificationWindow objects """
def setUp(self):
course = CourseFactory.create()
self.course_id = course.id
def setUp(self, **kwargs):
super(TestMidcourseReverificationWindow, self).setUp()
self.course_id = CourseFactory.create().id
def test_window_open_for_course(self):
# Should return False if no windows exist for a course
......
......@@ -177,18 +177,14 @@ class CourseEndingTest(TestCase):
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
class DashboardTest(TestCase):
class DashboardTest(ModuleStoreTestCase):
"""
Tests for dashboard utility functions
"""
# arbitrary constant
COURSE_SLUG = "100"
COURSE_NAME = "test_course"
COURSE_ORG = "EDX"
def setUp(self):
self.course = CourseFactory.create(org=self.COURSE_ORG, display_name=self.COURSE_NAME, number=self.COURSE_SLUG)
self.assertIsNotNone(self.course)
super(DashboardTest, self).setUp()
self.course = CourseFactory.create()
self.user = UserFactory.create(username="jack", email="jack@fake.edx.org", password='test')
self.client = Client()
......@@ -671,16 +667,11 @@ class PaidRegistrationTest(ModuleStoreTestCase):
"""
Tests for paid registration functionality (not verified student), involves shoppingcart
"""
# arbitrary constant
COURSE_SLUG = "100"
COURSE_NAME = "test_course"
COURSE_ORG = "EDX"
def setUp(self):
super(PaidRegistrationTest, self).setUp()
# Create course
self.course = CourseFactory.create()
self.req_factory = RequestFactory()
self.course = CourseFactory.create(org=self.COURSE_ORG, display_name=self.COURSE_NAME, number=self.COURSE_SLUG)
self.assertIsNotNone(self.course)
self.user = User.objects.create(username="jack", email="jack@fake.edx.org")
@unittest.skipUnless(settings.FEATURES.get('ENABLE_SHOPPING_CART'), "Shopping Cart not enabled in settings")
......@@ -705,18 +696,13 @@ class PaidRegistrationTest(ModuleStoreTestCase):
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
class AnonymousLookupTable(TestCase):
class AnonymousLookupTable(ModuleStoreTestCase):
"""
Tests for anonymous_id_functions
"""
# arbitrary constant
COURSE_SLUG = "100"
COURSE_NAME = "test_course"
COURSE_ORG = "EDX"
def setUp(self):
self.course = CourseFactory.create(org=self.COURSE_ORG, display_name=self.COURSE_NAME, number=self.COURSE_SLUG)
self.assertIsNotNone(self.course)
super(AnonymousLookupTable, self).setUp()
self.course = CourseFactory.create()
self.user = UserFactory()
CourseModeFactory.create(
course_id=self.course.id,
......@@ -739,7 +725,7 @@ class AnonymousLookupTable(TestCase):
self.assertEqual(anonymous_id, anonymous_id_for_user(self.user, self.course.id, save=False))
def test_roundtrip_with_unicode_course_id(self):
course2 = CourseFactory.create(org=self.COURSE_ORG, display_name=u"Omega Course Ω", number=self.COURSE_SLUG)
course2 = CourseFactory.create(display_name=u"Omega Course Ω")
CourseEnrollment.enroll(self.user, course2.id)
anonymous_id = anonymous_id_for_user(self.user, course2.id)
real_user = user_by_anonymous_id(anonymous_id)
......
......@@ -54,7 +54,6 @@ from verify_student.models import SoftwareSecurePhotoVerification, MidcourseReve
from certificates.models import CertificateStatuses, certificate_status_for_student
from dark_lang.models import DarkLangConfig
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.django import modulestore
from opaque_keys import InvalidKeyError
from opaque_keys.edx.locations import SlashSeparatedCourseKey
......@@ -697,6 +696,13 @@ def change_enrollment(request, auto_register=False, check_access=True):
del request.session['auto_register']
if action == "enroll":
# Make sure the course exists
# We don't do this check on unenroll, or a bad course id can't be unenrolled from
if not modulestore().has_course(course_id):
log.warning("User {0} tried to enroll in non-existent course {1}"
.format(user.username, course_id))
return HttpResponseBadRequest(_("Course id is invalid"))
# We use this flag to determine which condition of an AB-test
# for auto-registration we're currently in.
# (We have two URLs that both point to this view, but vary the
......
......@@ -6,13 +6,15 @@ from factory.containers import CyclicDefinitionError
from uuid import uuid4
from xmodule.modulestore import prefer_xmodules, ModuleStoreEnum
from opaque_keys.edx.locations import Location, SlashSeparatedCourseKey
from opaque_keys.edx.locations import Location
from opaque_keys.edx.keys import UsageKey
from xblock.core import XBlock
from xmodule.tabs import StaticTab
from decorator import contextmanager
from mock import Mock, patch
from nose.tools import assert_less_equal, assert_greater_equal, assert_equal
from nose.tools import assert_less_equal, assert_greater_equal
import factory
import threading
class Dummy(object):
......@@ -35,13 +37,16 @@ class XModuleFactory(Factory):
return modulestore()
last_course = threading.local()
class CourseFactory(XModuleFactory):
"""
Factory for XModule courses.
"""
org = 'MITx'
number = '999'
display_name = 'Robot Super Course'
org = factory.Sequence(lambda n: 'org.%d' % n)
number = factory.Sequence(lambda n: 'course_%d' % n)
display_name = factory.Sequence(lambda n: 'Run %d' % n)
# pylint: disable=unused-argument
@classmethod
......@@ -61,11 +66,8 @@ class CourseFactory(XModuleFactory):
with store.branch_setting(ModuleStoreEnum.Branch.draft_preferred):
# Write the data to the mongo datastore
kwargs.update(kwargs.get('metadata', {}))
course_key = SlashSeparatedCourseKey(org, number, run)
# TODO - We really should call create_course here. However, since create_course verifies there are no
# duplicates, this breaks several tests that do not clean up properly in between tests.
new_course = store.create_xblock(None, course_key, 'course', block_id=run, fields=kwargs)
store.update_item(new_course, user_id, allow_not_found=True)
new_course = store.create_course(org, number, run, user_id, fields=kwargs)
last_course.loc = new_course.location
return new_course
......@@ -96,7 +98,7 @@ class ItemFactory(XModuleFactory):
@lazy_attribute
def parent_location(self):
default_location = Location('MITx', '999', 'Robot_Super_Course', 'course', 'Robot_Super_Course', None)
default_location = getattr(last_course, 'loc', None)
try:
parent = self.parent
# This error is raised if the caller hasn't provided either parent or parent_location
......
......@@ -177,7 +177,7 @@ class AboutWithInvitationOnly(ModuleStoreTestCase):
url = reverse('about_course', args=[self.course.id.to_deprecated_string()])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn("Register for 999", resp.content)
self.assertIn(u"Register for {}".format(self.course.id.course), resp.content)
# Check that registration button is present
self.assertIn(REG_STR, resp.content)
......@@ -206,7 +206,7 @@ class AboutTestCaseShibCourse(LoginEnrollmentTestCase, ModuleStoreTestCase):
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn("OOGIE BLOOGIE", resp.content)
self.assertIn("Register for 999", resp.content)
self.assertIn(u"Register for {}".format(self.course.id.course), resp.content)
self.assertIn(SHIB_ERROR_STR, resp.content)
self.assertIn(REG_STR, resp.content)
......@@ -218,7 +218,7 @@ class AboutTestCaseShibCourse(LoginEnrollmentTestCase, ModuleStoreTestCase):
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn("OOGIE BLOOGIE", resp.content)
self.assertIn("Register for 999", resp.content)
self.assertIn(u"Register for {}".format(self.course.id.course), resp.content)
self.assertIn(SHIB_ERROR_STR, resp.content)
self.assertIn(REG_STR, resp.content)
......
......@@ -558,6 +558,7 @@ class ViewInStudioTest(ModuleStoreTestCase):
descriptor = ItemFactory.create(
category='vertical',
parent_location=course.location,
)
child_descriptor = ItemFactory.create(
......
......@@ -25,9 +25,9 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
STUDENT_INFO = [('view@test.com', 'foo'), ('view2@test.com', 'foo')]
def setUp(self):
self.test_course = CourseFactory.create(display_name='Robot_Sub_Course')
self.course = CourseFactory.create(display_name='Robot_Super_Course')
super(TestNavigation, self).setUp()
self.test_course = CourseFactory.create()
self.course = CourseFactory.create()
self.chapter0 = ItemFactory.create(parent=self.course,
display_name='Overview')
self.chapter9 = ItemFactory.create(parent=self.course,
......@@ -57,7 +57,7 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
chrome='accordion,tabs')
self.tabtest = ItemFactory.create(parent=self.chapterchrome,
display_name='progress_tab',
default_tab = 'progress')
default_tab='progress')
# Create student accounts and activate them.
for i in range(len(self.STUDENT_INFO)):
......@@ -73,7 +73,7 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
for line in response.content.split('\n'):
if tabname in line and 'active' in line:
return
raise AssertionError("assertTabActive failed: "+tabname+" not active")
raise AssertionError("assertTabActive failed: {} not active".format(tabname))
def assertTabInactive(self, tabname, response):
''' Check if the progress tab is active in the tab set '''
......@@ -98,7 +98,7 @@ class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase):
('fullchrome', True, True),
('accordion', True, False),
('fullchrome', True, True)
)
)
for (displayname, accordion, tabs) in test_data:
response = self.client.get(reverse('courseware_section', kwargs={
'course_id': self.course.id.to_deprecated_string(),
......
......@@ -101,7 +101,9 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase):
problem_location = self.problem_location(problem_url_name)
modx_url = self.modx_url(problem_location, 'problem_check')
answer_key_prefix = 'input_i4x-' + self.course.org + '-{}-problem-{}_'.format(self.COURSE_SLUG, problem_url_name)
answer_key_prefix = 'input_i4x-{}-{}-problem-{}_'.format(
self.course.org, self.course.id.course, problem_url_name
)
# format the response dictionary to be sent in the post request by adding the above prefix to each key
response_dict = {(answer_key_prefix + k): v for k, v in responses.items()}
......
......@@ -82,11 +82,11 @@ class ViewsTestCase(TestCase):
Tests for views.py methods.
"""
def setUp(self):
self.course = CourseFactory()
self.chapter = ItemFactory(category='chapter', parent_location=self.course.location) # pylint: disable=no-member
self.section = ItemFactory(category='sequential', parent_location=self.chapter.location, due=datetime(2013, 9, 18, 11, 30, 00))
self.vertical = ItemFactory(category='vertical', parent_location=self.section.location)
self.component = ItemFactory(category='problem', parent_location=self.vertical.location)
self.course = CourseFactory.create()
self.chapter = ItemFactory.create(category='chapter', parent_location=self.course.location) # pylint: disable=no-member
self.section = ItemFactory.create(category='sequential', parent_location=self.chapter.location, due=datetime(2013, 9, 18, 11, 30, 00))
self.vertical = ItemFactory.create(category='vertical', parent_location=self.section.location)
self.component = ItemFactory.create(category='problem', parent_location=self.vertical.location)
self.course_key = self.course.id
self.user = User.objects.create(username='dummy', password='123456',
......@@ -383,11 +383,11 @@ class BaseDueDateTests(ModuleStoreTestCase):
:param course_kwargs: All kwargs are passed to through to the :class:`CourseFactory`
"""
course = CourseFactory(**course_kwargs)
chapter = ItemFactory(category='chapter', parent_location=course.location) # pylint: disable=no-member
section = ItemFactory(category='sequential', parent_location=chapter.location, due=datetime(2013, 9, 18, 11, 30, 00))
vertical = ItemFactory(category='vertical', parent_location=section.location)
ItemFactory(category='problem', parent_location=vertical.location)
course = CourseFactory.create(**course_kwargs)
chapter = ItemFactory.create(category='chapter', parent_location=course.location) # pylint: disable=no-member
section = ItemFactory.create(category='sequential', parent_location=chapter.location, due=datetime(2013, 9, 18, 11, 30, 00))
vertical = ItemFactory.create(category='vertical', parent_location=section.location)
ItemFactory.create(category='problem', parent_location=vertical.location)
course = modulestore().get_course(course.id) # pylint: disable=no-member
self.assertIsNotNone(course.get_children()[0].get_children()[0].due)
......@@ -499,7 +499,7 @@ class StartDateTests(ModuleStoreTestCase):
:param course_kwargs: All kwargs are passed to through to the :class:`CourseFactory`
"""
course = CourseFactory(start=datetime(2013, 9, 16, 7, 17, 28))
course = CourseFactory.create(start=datetime(2013, 9, 16, 7, 17, 28))
course = modulestore().get_course(course.id) # pylint: disable=no-member
return course
......@@ -548,18 +548,18 @@ class ProgressPageTests(ModuleStoreTestCase):
MakoMiddleware().process_request(self.request)
course = CourseFactory(
course = CourseFactory.create(
start=datetime(2013, 9, 16, 7, 17, 28),
grade_cutoffs={u'çü†øƒƒ': 0.75, 'Pass': 0.5},
)
self.course = modulestore().get_course(course.id) # pylint: disable=no-member
self.chapter = ItemFactory(category='chapter', parent_location=self.course.location) # pylint: disable=no-member
self.section = ItemFactory(category='sequential', parent_location=self.chapter.location)
self.vertical = ItemFactory(category='vertical', parent_location=self.section.location)
self.chapter = ItemFactory.create(category='chapter', parent_location=self.course.location) # pylint: disable=no-member
self.section = ItemFactory.create(category='sequential', parent_location=self.chapter.location)
self.vertical = ItemFactory.create(category='vertical', parent_location=self.section.location)
def test_pure_ungraded_xblock(self):
ItemFactory(category='acid', parent_location=self.vertical.location)
ItemFactory.create(category='acid', parent_location=self.vertical.location)
resp = views.progress(self.request, course_id=self.course.id.to_deprecated_string())
self.assertEqual(resp.status_code, 200)
......
......@@ -42,7 +42,7 @@ class DictionaryTestCase(TestCase):
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
class AccessUtilsTestCase(TestCase):
class AccessUtilsTestCase(ModuleStoreTestCase):
def setUp(self):
self.course = CourseFactory.create()
self.course_id = self.course.id
......
......@@ -26,6 +26,7 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
from submissions import api as sub_api
from student.models import anonymous_id_for_user
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
class TestSettableEnrollmentState(TestCase):
......@@ -431,7 +432,7 @@ class TestSendBetaRoleEmail(TestCase):
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
class TestGetEmailParams(TestCase):
class TestGetEmailParams(ModuleStoreTestCase):
"""
Test what URLs the function get_email_params returns under different
production-like conditions.
......
......@@ -218,34 +218,36 @@ class TestInstructorEnrollsStudent(ModuleStoreTestCase, LoginEnrollmentTestCase)
self.assertEqual(len(mail.outbox), 3)
self.assertEqual(
mail.outbox[0].subject,
'You have been enrolled in Robot Super Course'
'You have been enrolled in {}'.format(course.display_name)
)
self.assertEqual(
mail.outbox[0].body,
"Dear Autoenrolled Test\n\nYou have been enrolled in Robot Super Course "
"Dear Autoenrolled Test\n\nYou have been enrolled in {} "
"at edx.org by a member of the course staff. "
"The course should now appear on your edx.org dashboard.\n\n"
"To start accessing course materials, please visit "
"{}://edx.org/courses/MITx/999/Robot_Super_Course/\n\n"
"----\nThis email was automatically sent from edx.org to Autoenrolled Test".format(protocol)
"{}://edx.org/courses/{}/\n\n"
"----\nThis email was automatically sent from edx.org to Autoenrolled Test".format(
course.display_name, protocol, unicode(course.id)
)
)
self.assertEqual(
mail.outbox[1].subject,
'You have been invited to register for Robot Super Course'
'You have been invited to register for {}'.format(course.display_name)
)
self.assertEqual(
mail.outbox[1].body,
"Dear student,\n\nYou have been invited to join "
"Robot Super Course at edx.org by a member of the "
"{display_name} at edx.org by a member of the "
"course staff.\n\n"
"To finish your registration, please visit "
"{}://edx.org/register and fill out the registration form "
"making sure to use student3_1@test.com in the E-mail field.\n"
"Once you have registered and activated your account, you will "
"see Robot Super Course listed on your dashboard.\n\n"
"see {display_name} listed on your dashboard.\n\n"
"----\nThis email was automatically sent from edx.org to "
"student3_1@test.com".format(protocol)
"student3_1@test.com".format(protocol, display_name=course.display_name)
)
def test_unenrollment_email_on(self):
......@@ -271,19 +273,19 @@ class TestInstructorEnrollsStudent(ModuleStoreTestCase, LoginEnrollmentTestCase)
self.assertEqual(len(mail.outbox), 3)
self.assertEqual(
mail.outbox[0].subject,
'You have been un-enrolled from Robot Super Course'
'You have been un-enrolled from {}'.format(course.display_name)
)
self.assertEqual(
mail.outbox[0].body,
"Dear Student,\n\nYou have been un-enrolled from course "
"Robot Super Course by a member of the course staff. "
"{} by a member of the course staff. "
"Please disregard the invitation previously sent.\n\n"
"----\nThis email was automatically sent from edx.org "
"to student4_0@test.com"
"to student4_0@test.com".format(course.display_name)
)
self.assertEqual(
mail.outbox[1].subject,
'You have been un-enrolled from Robot Super Course'
'You have been un-enrolled from {}'.format(course.display_name)
)
def test_send_mail_to_student(self):
......@@ -322,28 +324,32 @@ class TestInstructorEnrollsStudent(ModuleStoreTestCase, LoginEnrollmentTestCase)
self.assertEqual(len(mail.outbox), 2)
self.assertEqual(
mail.outbox[0].subject,
'You have been enrolled in Robot Super Course'
'You have been enrolled in {}'.format(course.display_name)
)
self.assertEqual(
mail.outbox[0].body,
"Dear ShibTest Enrolled\n\nYou have been enrolled in Robot Super Course "
"Dear ShibTest Enrolled\n\nYou have been enrolled in {} "
"at edx.org by a member of the course staff. "
"The course should now appear on your edx.org dashboard.\n\n"
"To start accessing course materials, please visit "
"{}://edx.org/courses/MITx/999/Robot_Super_Course/\n\n"
"----\nThis email was automatically sent from edx.org to ShibTest Enrolled".format(protocol)
"{}://edx.org/courses/{}/\n\n"
"----\nThis email was automatically sent from edx.org to ShibTest Enrolled".format(
course.display_name, protocol, unicode(course.id)
)
)
self.assertEqual(
mail.outbox[1].subject,
'You have been invited to register for Robot Super Course'
'You have been invited to register for {}'.format(course.display_name)
)
self.assertEqual(
mail.outbox[1].body,
"Dear student,\n\nYou have been invited to join "
"Robot Super Course at edx.org by a member of the "
"{} at edx.org by a member of the "
"course staff.\n\n"
"To access the course visit {}://edx.org/courses/MITx/999/Robot_Super_Course/ and login.\n\n"
"To access the course visit {}://edx.org/courses/{}/ and login.\n\n"
"----\nThis email was automatically sent from edx.org to "
"student5_1@test.com".format(protocol)
"student5_1@test.com".format(
course.display_name, protocol, course.id
)
)
......@@ -103,10 +103,12 @@ class TestCourseSaleRecordsAnalyticsBasic(ModuleStoreTestCase):
class TestCourseRegistrationCodeAnalyticsBasic(ModuleStoreTestCase):
""" Test basic course registration codes analytics functions. """
def setUp(self):
"""
Fixtures.
"""
super(TestCourseRegistrationCodeAnalyticsBasic, self).setUp()
self.course = CourseFactory.create()
self.instructor = InstructorFactory(course_key=self.course.id)
self.client.login(username=self.instructor.username, password='test')
......
......@@ -4,7 +4,7 @@ Tests for the Shopping Cart Models
import smtplib
from boto.exception import BotoServerError # this is a super-class of SESError and catches connection errors
from mock import patch, MagicMock, sentinel
from mock import patch, MagicMock
from django.core import mail
from django.conf import settings
from django.db import DatabaseError
......@@ -13,7 +13,6 @@ from django.test.utils import override_settings
from django.contrib.auth.models import AnonymousUser
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
from shoppingcart.models import (Order, OrderItem, CertificateItem, InvalidCartItem, PaidCourseRegistration,
OrderItemSubclassPK)
......@@ -23,16 +22,18 @@ from course_modes.models import CourseMode
from shoppingcart.exceptions import PurchasedCallbackException
import pytz
import datetime
from opaque_keys.edx.locations import SlashSeparatedCourseKey
@override_settings(MODULESTORE=TEST_DATA_MONGO_MODULESTORE)
class OrderTest(ModuleStoreTestCase):
def setUp(self):
self.user = UserFactory.create()
course = CourseFactory.create(org='org', number='test', display_name='Test Course')
course = CourseFactory.create()
self.course_key = course.id
self.other_course_keys = []
for i in xrange(1, 5):
CourseFactory.create(org='org', number='test', display_name='Test Course {0}'.format(i))
self.other_course_keys.append(CourseFactory.create())
self.cost = 40
def test_get_cart_for_user(self):
......@@ -71,7 +72,7 @@ class OrderTest(ModuleStoreTestCase):
def test_cart_clear(self):
cart = Order.get_cart_for_user(user=self.user)
CertificateItem.add_to_order(cart, self.course_key, self.cost, 'honor')
CertificateItem.add_to_order(cart, SlashSeparatedCourseKey('org', 'test', 'Test_Course_1'), self.cost, 'honor')
CertificateItem.add_to_order(cart, self.other_course_keys[0], self.cost, 'honor')
self.assertEquals(cart.orderitem_set.count(), 2)
self.assertTrue(cart.has_items())
cart.clear()
......@@ -93,12 +94,12 @@ class OrderTest(ModuleStoreTestCase):
def test_total_cost(self):
cart = Order.get_cart_for_user(user=self.user)
# add items to the order
course_costs = [('org/test/Test_Course_1', 30),
('org/test/Test_Course_2', 40),
('org/test/Test_Course_3', 10),
('org/test/Test_Course_4', 20)]
course_costs = [(self.other_course_keys[0], 30),
(self.other_course_keys[1], 40),
(self.other_course_keys[2], 10),
(self.other_course_keys[3], 20)]
for course, cost in course_costs:
CertificateItem.add_to_order(cart, SlashSeparatedCourseKey.from_deprecated_string(course), cost, 'honor')
CertificateItem.add_to_order(cart, course, cost, 'honor')
self.assertEquals(cart.orderitem_set.count(), len(course_costs))
self.assertEquals(cart.total_cost, sum(cost for _course, cost in course_costs))
......@@ -290,7 +291,7 @@ class PaidCourseRegistrationTest(ModuleStoreTestCase):
def setUp(self):
self.user = UserFactory.create()
self.cost = 40
self.course = CourseFactory.create(org='MITx', number='999', display_name='Robot Super Course')
self.course = CourseFactory.create()
self.course_key = self.course.id
self.course_mode = CourseMode(course_id=self.course_key,
mode_slug="honor",
......@@ -309,7 +310,9 @@ class PaidCourseRegistrationTest(ModuleStoreTestCase):
self.assertEqual(reg1.user, self.user)
self.assertEqual(reg1.status, "cart")
self.assertTrue(PaidCourseRegistration.contained_in_order(self.cart, self.course_key))
self.assertFalse(PaidCourseRegistration.contained_in_order(self.cart, SlashSeparatedCourseKey("MITx", "999", "Robot_Super_Course_abcd")))
self.assertFalse(PaidCourseRegistration.contained_in_order(
self.cart, SlashSeparatedCourseKey("MITx", "999", "Robot_Super_Course_abcd"))
)
self.assertEqual(self.cart.total_cost, self.cost)
......@@ -339,7 +342,7 @@ class PaidCourseRegistrationTest(ModuleStoreTestCase):
"""
Add 2 courses to the order and make sure the instruction_set only contains 1 element (no dups)
"""
course2 = CourseFactory.create(org='MITx', number='998', display_name='Robot Duper Course')
course2 = CourseFactory.create()
course_mode2 = CourseMode(course_id=course2.id,
mode_slug="honor",
mode_display_name="honor cert",
......@@ -388,7 +391,7 @@ class CertificateItemTest(ModuleStoreTestCase):
def setUp(self):
self.user = UserFactory.create()
self.cost = 40
course = CourseFactory.create(org='org', number='test', display_name='Test Course')
course = CourseFactory.create()
self.course_key = course.id
course_mode = CourseMode(course_id=self.course_key,
mode_slug="honor",
......@@ -444,7 +447,7 @@ class CertificateItemTest(ModuleStoreTestCase):
# If the expiration date has not yet passed on a verified mode, the user can be refunded
many_days = datetime.timedelta(days=60)
course = CourseFactory.create(org='refund_before_expiration', number='test', display_name='one')
course = CourseFactory.create()
course_key = course.id
course_mode = CourseMode(course_id=course_key,
mode_slug="verified",
......@@ -466,7 +469,7 @@ class CertificateItemTest(ModuleStoreTestCase):
def test_refund_cert_callback_before_expiration_email(self):
""" Test that refund emails are being sent correctly. """
course = CourseFactory.create(org='refund_before_expiration', number='test', run='course', display_name='one')
course = CourseFactory.create()
course_key = course.id
many_days = datetime.timedelta(days=60)
......@@ -496,7 +499,7 @@ class CertificateItemTest(ModuleStoreTestCase):
# If there's an error sending an email to billing, we need to log this error
many_days = datetime.timedelta(days=60)
course = CourseFactory.create(org='refund_before_expiration', number='test', display_name='one')
course = CourseFactory.create()
course_key = course.id
course_mode = CourseMode(course_id=course_key,
......@@ -519,7 +522,7 @@ class CertificateItemTest(ModuleStoreTestCase):
# If the expiration date has passed, the user cannot get a refund
many_days = datetime.timedelta(days=60)
course = CourseFactory.create(org='refund_after_expiration', number='test', display_name='two')
course = CourseFactory.create()
course_key = course.id
course_mode = CourseMode(course_id=course_key,
mode_slug="verified",
......
......@@ -10,7 +10,6 @@ from django.test import TestCase
from courseware.tests.tests import TEST_DATA_MONGO_MODULESTORE
from django.test.utils import override_settings
from django.conf import settings
import requests
import requests.exceptions
from student.tests.factories import UserFactory
......@@ -18,10 +17,11 @@ from verify_student.models import (
SoftwareSecurePhotoVerification, VerificationException,
)
from reverification.tests.factories import MidcourseReverificationWindowFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
FAKE_SETTINGS = {
"SOFTWARE_SECURE": {
"FACE_IMAGE_AES_KEY" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"FACE_IMAGE_AES_KEY": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"API_ACCESS_KEY": "BBBBBBBBBBBBBBBBBBBB",
"API_SECRET_KEY": "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC",
"RSA_PUBLIC_KEY": """-----BEGIN PUBLIC KEY-----
......@@ -420,10 +420,12 @@ class TestPhotoVerification(TestCase):
@patch('verify_student.models.S3Connection', new=MockS3Connection)
@patch('verify_student.models.Key', new=MockKey)
@patch('verify_student.models.requests.post', new=mock_software_secure_post)
class TestMidcourseReverification(TestCase):
class TestMidcourseReverification(ModuleStoreTestCase):
""" Tests for methods that are specific to midcourse SoftwareSecurePhotoVerification objects """
def setUp(self):
self.course = CourseFactory.create(org='MITx', number='999', display_name='Robot Super Course')
super(TestMidcourseReverification, self).setUp()
self.course = CourseFactory.create()
self.user = UserFactory.create()
def test_user_is_reverified_for_all(self):
......
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