From 434f19655032e6d6e42240fa0d2fbd4308dd79a4 Mon Sep 17 00:00:00 2001 From: Matjaz Gregoric Date: Sun, 24 Jan 2016 19:31:39 +0100 Subject: [PATCH 01/60] Remove default django template loaders. Mako filesystem/app_directories loaders already wrap default django template loaders. Mako loaders delegate the `load_template_source` method to the base loader that they wrap, so there's no reason to explicitly include the two django loaders in the settings. --- common/djangoapps/edxmako/makoloader.py | 1 + lms/envs/common.py | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/common/djangoapps/edxmako/makoloader.py b/common/djangoapps/edxmako/makoloader.py index 994346a2ba0d..cfe1915564ed 100644 --- a/common/djangoapps/edxmako/makoloader.py +++ b/common/djangoapps/edxmako/makoloader.py @@ -19,6 +19,7 @@ class MakoLoader(object): This is a Django loader object which will load the template as a Mako template if the first line is "## mako". It is based off BaseLoader in django.template.loader. + We need this in order to be able to include mako templates inside main_django.html. """ is_usable = False diff --git a/lms/envs/common.py b/lms/envs/common.py index 68fcc3e6c778..33e41b6333b3 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -472,12 +472,10 @@ # Options specific to this backend. 'OPTIONS': { 'loaders': [ + # We have to use mako-aware template loaders to be able to include + # mako templates inside django templates (such as main_django.html). 'edxmako.makoloader.MakoFilesystemLoader', 'edxmako.makoloader.MakoAppDirectoriesLoader', - - 'django.template.loaders.filesystem.Loader', - 'django.template.loaders.app_directories.Loader', - ], 'context_processors': [ 'django.template.context_processors.request', From ad9498ecf4721a52c39b9bfdb110e6928b5828f7 Mon Sep 17 00:00:00 2001 From: Toby Lawrence Date: Fri, 5 Feb 2016 08:41:05 -0500 Subject: [PATCH 02/60] Switch to SharedModuleStoreTestCase in the 'courseware' app where possible. --- lms/djangoapps/courseware/tests/test_about.py | 120 +++++++++++------- .../courseware/tests/test_course_info.py | 24 ++-- .../courseware/tests/test_course_survey.py | 36 +++--- .../tests/test_credit_requirements.py | 12 +- .../courseware/tests/test_field_overrides.py | 2 +- .../courseware/tests/test_grades.py | 109 +++++++++------- .../courseware/tests/test_lti_integration.py | 44 ++++--- .../courseware/tests/test_masquerade.py | 48 +++---- .../courseware/tests/test_microsites.py | 38 +++--- .../courseware/tests/test_middleware.py | 11 +- .../courseware/tests/test_module_render.py | 95 ++++++++++---- .../courseware/tests/test_navigation.py | 42 +++--- .../courseware/tests/test_split_module.py | 49 ++++--- .../tests/test_submitting_problems.py | 9 +- lms/djangoapps/courseware/tests/test_tabs.py | 48 ++++--- 15 files changed, 400 insertions(+), 287 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_about.py b/lms/djangoapps/courseware/tests/test_about.py index de00034ce321..94911660382a 100644 --- a/lms/djangoapps/courseware/tests/test_about.py +++ b/lms/djangoapps/courseware/tests/test_about.py @@ -41,29 +41,34 @@ @attr('shard_1') -class AboutTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase, EventTrackingTestCase, MilestonesTestCaseMixin): +class AboutTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase, EventTrackingTestCase, MilestonesTestCaseMixin): """ Tests about xblock. """ - def setUp(self): - super(AboutTestCase, self).setUp() - self.course = CourseFactory.create() - self.about = ItemFactory.create( - category="about", parent_location=self.course.location, + + @classmethod + def setUpClass(cls): + super(AboutTestCase, cls).setUpClass() + cls.course = CourseFactory.create() + cls.course_without_about = CourseFactory.create(catalog_visibility=CATALOG_VISIBILITY_NONE) + cls.course_with_about = CourseFactory.create(catalog_visibility=CATALOG_VISIBILITY_ABOUT) + cls.purchase_course = CourseFactory.create(org='MITx', number='buyme', display_name='Course To Buy') + cls.about = ItemFactory.create( + category="about", parent_location=cls.course.location, data="OOGIE BLOOGIE", display_name="overview" ) - self.course_without_about = CourseFactory.create(catalog_visibility=CATALOG_VISIBILITY_NONE) - self.about = ItemFactory.create( - category="about", parent_location=self.course_without_about.location, + cls.about = ItemFactory.create( + category="about", parent_location=cls.course_without_about.location, data="WITHOUT ABOUT", display_name="overview" ) - self.course_with_about = CourseFactory.create(catalog_visibility=CATALOG_VISIBILITY_ABOUT) - self.about = ItemFactory.create( - category="about", parent_location=self.course_with_about.location, + cls.about = ItemFactory.create( + category="about", parent_location=cls.course_with_about.location, data="WITH ABOUT", display_name="overview" ) - self.purchase_course = CourseFactory.create(org='MITx', number='buyme', display_name='Course To Buy') + def setUp(self): + super(AboutTestCase, self).setUp() + self.course_mode = CourseMode( course_id=self.purchase_course.id, mode_slug=CourseMode.DEFAULT_MODE_SLUG, @@ -152,7 +157,7 @@ def test_pre_requisite_course(self): def test_about_page_unfulfilled_prereqs(self): pre_requisite_course = CourseFactory.create( org='edX', - course='900', + course='901', display_name='pre requisite course', ) @@ -222,21 +227,24 @@ def test_anonymous_user_xml(self): @attr('shard_1') -class AboutWithCappedEnrollmentsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase): +class AboutWithCappedEnrollmentsTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase): """ This test case will check the About page when a course has a capped enrollment """ + @classmethod + def setUpClass(cls): + super(AboutWithCappedEnrollmentsTestCase, cls).setUpClass() + cls.course = CourseFactory.create(metadata={"max_student_enrollments_allowed": 1}) + cls.about = ItemFactory.create( + category="about", parent_location=cls.course.location, + data="OOGIE BLOOGIE", display_name="overview" + ) + def setUp(self): """ Set up the tests """ super(AboutWithCappedEnrollmentsTestCase, self).setUp() - self.course = CourseFactory.create(metadata={"max_student_enrollments_allowed": 1}) - - self.about = ItemFactory.create( - category="about", parent_location=self.course.location, - data="OOGIE BLOOGIE", display_name="overview" - ) def test_enrollment_cap(self): """ @@ -272,20 +280,22 @@ def test_enrollment_cap(self): @attr('shard_1') -class AboutWithInvitationOnly(ModuleStoreTestCase): +class AboutWithInvitationOnly(SharedModuleStoreTestCase): """ This test case will check the About page when a course is invitation only. """ - def setUp(self): - super(AboutWithInvitationOnly, self).setUp() - - self.course = CourseFactory.create(metadata={"invitation_only": True}) - - self.about = ItemFactory.create( - category="about", parent_location=self.course.location, + @classmethod + def setUpClass(cls): + super(AboutWithInvitationOnly, cls).setUpClass() + cls.course = CourseFactory.create(metadata={"invitation_only": True}) + cls.about = ItemFactory.create( + category="about", parent_location=cls.course.location, display_name="overview" ) + def setUp(self): + super(AboutWithInvitationOnly, self).setUp() + def test_invitation_only(self): """ Test for user not logged in, invitation only course. @@ -320,19 +330,22 @@ def test_invitation_only_but_allowed(self): @attr('shard_1') @patch.dict(settings.FEATURES, {'RESTRICT_ENROLL_BY_REG_METHOD': True}) -class AboutTestCaseShibCourse(LoginEnrollmentTestCase, ModuleStoreTestCase): +class AboutTestCaseShibCourse(LoginEnrollmentTestCase, SharedModuleStoreTestCase): """ Test cases covering about page behavior for courses that use shib enrollment domain ("shib courses") """ - def setUp(self): - super(AboutTestCaseShibCourse, self).setUp() - self.course = CourseFactory.create(enrollment_domain="shib:https://idp.stanford.edu/") - - self.about = ItemFactory.create( - category="about", parent_location=self.course.location, + @classmethod + def setUpClass(cls): + super(AboutTestCaseShibCourse, cls).setUpClass() + cls.course = CourseFactory.create(enrollment_domain="shib:https://idp.stanford.edu/") + cls.about = ItemFactory.create( + category="about", parent_location=cls.course.location, data="OOGIE BLOOGIE", display_name="overview" ) + def setUp(self): + super(AboutTestCaseShibCourse, self).setUp() + def test_logged_in_shib_course(self): """ For shib courses, logged in users will see the enroll button, but get rejected once they click there @@ -366,8 +379,8 @@ class AboutWithClosedEnrollment(ModuleStoreTestCase): set but it is currently outside of that period. """ def setUp(self): - super(AboutWithClosedEnrollment, self).setUp() + self.course = CourseFactory.create(metadata={"invitation_only": False}) # Setup enrollment period to be in future @@ -385,7 +398,6 @@ def setUp(self): ) def test_closed_enrollmement(self): - url = reverse('about_course', args=[self.course.id.to_deprecated_string()]) resp = self.client.get(url) self.assertEqual(resp.status_code, 200) @@ -406,15 +418,32 @@ def test_course_price_is_not_visble_in_sidebar(self): @attr('shard_1') @patch.dict(settings.FEATURES, {'ENABLE_SHOPPING_CART': True}) @patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True}) -class AboutPurchaseCourseTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase): +class AboutPurchaseCourseTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase): """ This test class runs through a suite of verifications regarding purchaseable courses """ + @classmethod + def setUpClass(cls): + super(AboutPurchaseCourseTestCase, cls).setUpClass() + cls.course = CourseFactory.create(org='MITx', number='buyme', display_name='Course To Buy') + + now = datetime.datetime.now(pytz.UTC) + tomorrow = now + datetime.timedelta(days=1) + nextday = tomorrow + datetime.timedelta(days=1) + + cls.closed_course = CourseFactory.create( + org='MITx', + number='closed', + display_name='Closed Course To Buy', + enrollment_start = tomorrow, + enrollment_end = nextday + ) + def setUp(self): super(AboutPurchaseCourseTestCase, self).setUp() - self.course = CourseFactory.create(org='MITx', number='buyme', display_name='Course To Buy') self._set_ecomm(self.course) + self._set_ecomm(self.closed_course) def _set_ecomm(self, course): """ @@ -487,19 +516,12 @@ def test_closed_enrollment(self): window """ self.setup_user() - now = datetime.datetime.now(pytz.UTC) - tomorrow = now + datetime.timedelta(days=1) - nextday = tomorrow + datetime.timedelta(days=1) - - self.course.enrollment_start = tomorrow - self.course.enrollment_end = nextday - self.course = self.update_course(self.course, self.user.id) - url = reverse('about_course', args=[self.course.id.to_deprecated_string()]) + url = reverse('about_course', args=[self.closed_course.id.to_deprecated_string()]) resp = self.client.get(url) self.assertEqual(resp.status_code, 200) self.assertIn("Enrollment is Closed", resp.content) - self.assertNotIn("Add buyme to Cart ($10 USD)", resp.content) + self.assertNotIn("Add closed to Cart ($10 USD)", resp.content) # course price is visible ihe course_about page when the course # mode is set to honor and it's price is set diff --git a/lms/djangoapps/courseware/tests/test_course_info.py b/lms/djangoapps/courseware/tests/test_course_info.py index 9a600413bc79..6a5547867efd 100644 --- a/lms/djangoapps/courseware/tests/test_course_info.py +++ b/lms/djangoapps/courseware/tests/test_course_info.py @@ -30,18 +30,22 @@ @attr('shard_1') -class CourseInfoTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase): +class CourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase): """ Tests for the Course Info page """ - def setUp(self): - super(CourseInfoTestCase, self).setUp() - self.course = CourseFactory.create() - self.page = ItemFactory.create( - category="course_info", parent_location=self.course.location, + @classmethod + def setUpClass(cls): + super(CourseInfoTestCase, cls).setUpClass() + cls.course = CourseFactory.create() + cls.page = ItemFactory.create( + category="course_info", parent_location=cls.course.location, data="OOGIE BLOOGIE", display_name="updates" ) + def setUp(self): + super(CourseInfoTestCase, self).setUp() + def test_logged_in_unenrolled(self): self.setup_user() url = reverse('info', args=[self.course.id.to_deprecated_string()]) @@ -203,11 +207,15 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest Tests for the info page of self-paced courses. """ + @classmethod + def setUpClass(cls): + super(SelfPacedCourseInfoTestCase, cls).setUpClass() + cls.instructor_paced_course = CourseFactory.create(self_paced=False) + cls.self_paced_course = CourseFactory.create(self_paced=True) + def setUp(self): SelfPacedConfiguration(enabled=True).save() super(SelfPacedCourseInfoTestCase, self).setUp() - self.instructor_paced_course = CourseFactory.create(self_paced=False) - self.self_paced_course = CourseFactory.create(self_paced=True) self.setup_user() def fetch_course_info_with_queries(self, course, sql_queries, mongo_queries): diff --git a/lms/djangoapps/courseware/tests/test_course_survey.py b/lms/djangoapps/courseware/tests/test_course_survey.py index 05f2386bff8c..c52128af7b6e 100644 --- a/lms/djangoapps/courseware/tests/test_course_survey.py +++ b/lms/djangoapps/courseware/tests/test_course_survey.py @@ -13,27 +13,42 @@ from common.test.utils import XssTestMixin from xmodule.modulestore.tests.factories import CourseFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from courseware.tests.helpers import LoginEnrollmentTestCase @attr('shard_1') -class SurveyViewsTests(LoginEnrollmentTestCase, ModuleStoreTestCase, XssTestMixin): +class SurveyViewsTests(LoginEnrollmentTestCase, SharedModuleStoreTestCase, XssTestMixin): """ All tests for the views.py file """ STUDENT_INFO = [('view@test.com', 'foo')] + @classmethod + def setUpClass(cls): + super(SurveyViewsTests, cls).setUpClass() + cls.test_survey_name = 'TestSurvey' + cls.course = CourseFactory.create( + display_name='', + course_survey_required=True, + course_survey_name=cls.test_survey_name + ) + + cls.course_with_bogus_survey = CourseFactory.create( + course_survey_required=True, + course_survey_name="DoesNotExist" + ) + + cls.course_without_survey = CourseFactory.create() + def setUp(self): """ Set up the test data used in the specific tests """ super(SurveyViewsTests, self).setUp() - self.test_survey_name = 'TestSurvey' self.test_form = '' - self.survey = SurveyForm.create(self.test_survey_name, self.test_form) self.student_answers = OrderedDict({ @@ -41,19 +56,6 @@ def setUp(self): u'field2': u'value2', }) - self.course = CourseFactory.create( - display_name='', - course_survey_required=True, - course_survey_name=self.test_survey_name - ) - - self.course_with_bogus_survey = CourseFactory.create( - course_survey_required=True, - course_survey_name="DoesNotExist" - ) - - self.course_without_survey = CourseFactory.create() - # Create student accounts and activate them. for i in range(len(self.STUDENT_INFO)): email, password = self.STUDENT_INFO[i] diff --git a/lms/djangoapps/courseware/tests/test_credit_requirements.py b/lms/djangoapps/courseware/tests/test_credit_requirements.py index d449137d9224..87fc3c2c4267 100644 --- a/lms/djangoapps/courseware/tests/test_credit_requirements.py +++ b/lms/djangoapps/courseware/tests/test_credit_requirements.py @@ -11,7 +11,7 @@ from django.conf import settings from django.core.urlresolvers import reverse -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory from util.date_utils import get_time_display, DEFAULT_SHORT_DATE_FORMAT @@ -23,7 +23,7 @@ @patch.dict(settings.FEATURES, {"ENABLE_CREDIT_ELIGIBILITY": True}) @ddt.ddt -class ProgressPageCreditRequirementsTest(ModuleStoreTestCase): +class ProgressPageCreditRequirementsTest(SharedModuleStoreTestCase): """ Tests for credit requirement display on the progress page. """ @@ -35,11 +35,15 @@ class ProgressPageCreditRequirementsTest(ModuleStoreTestCase): MIN_GRADE_REQ_DISPLAY = "Final Grade Credit Requirement" VERIFICATION_REQ_DISPLAY = "Midterm Exam Credit Requirement" + @classmethod + def setUpClass(cls): + super(ProgressPageCreditRequirementsTest, cls).setUpClass() + cls.course = CourseFactory.create() + def setUp(self): super(ProgressPageCreditRequirementsTest, self).setUp() - # Create a course and configure it as a credit course - self.course = CourseFactory.create() + # Configure course as a credit course CreditCourse.objects.create(course_key=self.course.id, enabled=True) # Configure credit requirements (passing grade and in-course reverification) diff --git a/lms/djangoapps/courseware/tests/test_field_overrides.py b/lms/djangoapps/courseware/tests/test_field_overrides.py index 24f6d6185997..e0bec1b485ea 100644 --- a/lms/djangoapps/courseware/tests/test_field_overrides.py +++ b/lms/djangoapps/courseware/tests/test_field_overrides.py @@ -9,7 +9,7 @@ from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.django_utils import ( ModuleStoreTestCase, -) + SharedModuleStoreTestCase) from ..field_overrides import ( disable_overrides, diff --git a/lms/djangoapps/courseware/tests/test_grades.py b/lms/djangoapps/courseware/tests/test_grades.py index 4b43ec2a8d12..9168429c2a81 100644 --- a/lms/djangoapps/courseware/tests/test_grades.py +++ b/lms/djangoapps/courseware/tests/test_grades.py @@ -28,7 +28,7 @@ from student.tests.factories import UserFactory from student.models import CourseEnrollment from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase def _grade_with_errors(student, request, course, keep_raw_scores=False): @@ -46,23 +46,27 @@ def _grade_with_errors(student, request, course, keep_raw_scores=False): @attr('shard_1') -class TestGradeIteration(ModuleStoreTestCase): +class TestGradeIteration(SharedModuleStoreTestCase): """ Test iteration through student gradesets. """ COURSE_NUM = "1000" COURSE_NAME = "grading_test_course" + @classmethod + def setUpClass(cls): + super(TestGradeIteration, cls).setUpClass() + cls.course = CourseFactory.create( + display_name=cls.COURSE_NAME, + number=cls.COURSE_NUM + ) + def setUp(self): """ Create a course and a handful of users to assign grades """ super(TestGradeIteration, self).setUp() - self.course = CourseFactory.create( - display_name=self.COURSE_NAME, - number=self.COURSE_NUM - ) self.students = [ UserFactory.create(username='student1'), UserFactory.create(username='student2'), @@ -142,19 +146,24 @@ def _gradesets_and_errors_for(self, course_id, students): return students_to_gradesets, students_to_errors -class TestMaxScoresCache(ModuleStoreTestCase): +class TestMaxScoresCache(SharedModuleStoreTestCase): """ Tests for the MaxScoresCache """ + + @classmethod + def setUpClass(cls): + super(TestMaxScoresCache, cls).setUpClass() + cls.course = CourseFactory.create() + cls.problems = [] + for _ in xrange(3): + cls.problems.append( + ItemFactory.create(category='problem', parent=cls.course) + ) + def setUp(self): super(TestMaxScoresCache, self).setUp() self.student = UserFactory.create() - self.course = CourseFactory.create() - self.problems = [] - for _ in xrange(3): - self.problems.append( - ItemFactory.create(category='problem', parent=self.course) - ) CourseEnrollment.enroll(self.student, self.course.id) self.request = RequestFactory().get('/') @@ -183,16 +192,16 @@ def test_max_scores_cache(self): self.assertEqual(max_scores_cache.num_cached_from_remote(), 1) -class TestFieldDataCacheScorableLocations(ModuleStoreTestCase): +class TestFieldDataCacheScorableLocations(SharedModuleStoreTestCase): """ Make sure we can filter the locations we pull back student state for via the FieldDataCache. """ - def setUp(self): - super(TestFieldDataCacheScorableLocations, self).setUp() - self.student = UserFactory.create() - self.course = CourseFactory.create() - chapter = ItemFactory.create(category='chapter', parent=self.course) + @classmethod + def setUpClass(cls): + super(TestFieldDataCacheScorableLocations, cls).setUpClass() + cls.course = CourseFactory.create() + chapter = ItemFactory.create(category='chapter', parent=cls.course) sequential = ItemFactory.create(category='sequential', parent=chapter) vertical = ItemFactory.create(category='vertical', parent=sequential) ItemFactory.create(category='video', parent=vertical) @@ -200,6 +209,10 @@ def setUp(self): ItemFactory.create(category='discussion', parent=vertical) ItemFactory.create(category='problem', parent=vertical) + def setUp(self): + super(TestFieldDataCacheScorableLocations, self).setUp() + self.student = UserFactory.create() + CourseEnrollment.enroll(self.student, self.course.id) def test_field_data_cache_scorable_locations(self): @@ -334,45 +347,43 @@ def test_score_leaf_no_score(self): self.assertEqual(possible, 0) -class TestGetModuleScore(LoginEnrollmentTestCase, ModuleStoreTestCase): +class TestGetModuleScore(LoginEnrollmentTestCase, SharedModuleStoreTestCase): """ Test get_module_score """ - def setUp(self): - """ - Set up test course - """ - super(TestGetModuleScore, self).setUp() - self.course = CourseFactory.create() - self.chapter = ItemFactory.create( - parent=self.course, + @classmethod + def setUpClass(cls): + super(TestGetModuleScore, cls).setUpClass() + cls.course = CourseFactory.create() + cls.chapter = ItemFactory.create( + parent=cls.course, category="chapter", display_name="Test Chapter" ) - self.seq1 = ItemFactory.create( - parent=self.chapter, + cls.seq1 = ItemFactory.create( + parent=cls.chapter, category='sequential', display_name="Test Sequential", graded=True ) - self.seq2 = ItemFactory.create( - parent=self.chapter, + cls.seq2 = ItemFactory.create( + parent=cls.chapter, category='sequential', display_name="Test Sequential", graded=True ) - self.vert1 = ItemFactory.create( - parent=self.seq1, + cls.vert1 = ItemFactory.create( + parent=cls.seq1, category='vertical', display_name='Test Vertical 1' ) - self.vert2 = ItemFactory.create( - parent=self.seq2, + cls.vert2 = ItemFactory.create( + parent=cls.seq2, category='vertical', display_name='Test Vertical 2' ) - self.randomize = ItemFactory.create( - parent=self.vert2, + cls.randomize = ItemFactory.create( + parent=cls.vert2, category='randomize', display_name='Test Randomize' ) @@ -381,31 +392,37 @@ def setUp(self): choices=[False, False, True, False], choice_names=['choice_0', 'choice_1', 'choice_2', 'choice_3'] ) - self.problem1 = ItemFactory.create( - parent=self.vert1, + cls.problem1 = ItemFactory.create( + parent=cls.vert1, category="problem", display_name="Test Problem 1", data=problem_xml ) - self.problem2 = ItemFactory.create( - parent=self.vert1, + cls.problem2 = ItemFactory.create( + parent=cls.vert1, category="problem", display_name="Test Problem 2", data=problem_xml ) - self.problem3 = ItemFactory.create( - parent=self.randomize, + cls.problem3 = ItemFactory.create( + parent=cls.randomize, category="problem", display_name="Test Problem 3", data=problem_xml ) - self.problem4 = ItemFactory.create( - parent=self.randomize, + cls.problem4 = ItemFactory.create( + parent=cls.randomize, category="problem", display_name="Test Problem 4", data=problem_xml ) + def setUp(self): + """ + Set up test course + """ + super(TestGetModuleScore, self).setUp() + self.request = get_request_for_user(UserFactory()) self.client.login(username=self.request.user.username, password="test") CourseEnrollment.enroll(self.request.user, self.course.id) diff --git a/lms/djangoapps/courseware/tests/test_lti_integration.py b/lms/djangoapps/courseware/tests/test_lti_integration.py index 91d9867b85f8..00b03b101b99 100644 --- a/lms/djangoapps/courseware/tests/test_lti_integration.py +++ b/lms/djangoapps/courseware/tests/test_lti_integration.py @@ -13,7 +13,7 @@ from courseware.tests import BaseTestXmodule from courseware.views import get_course_lti_endpoints from lms.djangoapps.lms_xblock.runtime import quote_slashes -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.x_module import STUDENT_VIEW @@ -125,7 +125,7 @@ def test_lti_preview_handler(self): @attr('shard_1') -class TestLTIModuleListing(ModuleStoreTestCase): +class TestLTIModuleListing(SharedModuleStoreTestCase): """ a test for the rest endpoint that lists LTI modules in a course """ @@ -133,42 +133,46 @@ class TestLTIModuleListing(ModuleStoreTestCase): COURSE_SLUG = "100" COURSE_NAME = "test_course" - def setUp(self): - """Create course, 2 chapters, 2 sections""" - super(TestLTIModuleListing, self).setUp() - self.course = CourseFactory.create(display_name=self.COURSE_NAME, number=self.COURSE_SLUG) - self.chapter1 = ItemFactory.create( - parent_location=self.course.location, + @classmethod + def setUpClass(cls): + super(TestLTIModuleListing, cls).setUpClass() + cls.course = CourseFactory.create(display_name=cls.COURSE_NAME, number=cls.COURSE_SLUG) + cls.chapter1 = ItemFactory.create( + parent_location=cls.course.location, display_name="chapter1", category='chapter') - self.section1 = ItemFactory.create( - parent_location=self.chapter1.location, + cls.section1 = ItemFactory.create( + parent_location=cls.chapter1.location, display_name="section1", category='sequential') - self.chapter2 = ItemFactory.create( - parent_location=self.course.location, + cls.chapter2 = ItemFactory.create( + parent_location=cls.course.location, display_name="chapter2", category='chapter') - self.section2 = ItemFactory.create( - parent_location=self.chapter2.location, + cls.section2 = ItemFactory.create( + parent_location=cls.chapter2.location, display_name="section2", category='sequential') # creates one draft and one published lti module, in different sections - self.lti_published = ItemFactory.create( - parent_location=self.section1.location, + cls.lti_published = ItemFactory.create( + parent_location=cls.section1.location, display_name="lti published", category="lti", - location=self.course.id.make_usage_key('lti', 'lti_published'), + location=cls.course.id.make_usage_key('lti', 'lti_published'), ) - self.lti_draft = ItemFactory.create( - parent_location=self.section2.location, + cls.lti_draft = ItemFactory.create( + parent_location=cls.section2.location, display_name="lti draft", category="lti", - location=self.course.id.make_usage_key('lti', 'lti_draft'), + location=cls.course.id.make_usage_key('lti', 'lti_draft'), publish_item=False, ) + def setUp(self): + """Create course, 2 chapters, 2 sections""" + super(TestLTIModuleListing, self).setUp() + def expected_handler_url(self, handler): """convenience method to get the reversed handler urls""" return "https://{}{}".format(settings.SITE_NAME, reverse( diff --git a/lms/djangoapps/courseware/tests/test_masquerade.py b/lms/djangoapps/courseware/tests/test_masquerade.py index 7e24283efa3a..539326b719fa 100644 --- a/lms/djangoapps/courseware/tests/test_masquerade.py +++ b/lms/djangoapps/courseware/tests/test_masquerade.py @@ -25,40 +25,36 @@ from student.tests.factories import UserFactory from xblock.runtime import DictKeyValueStore from xmodule.modulestore.django import modulestore -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory from xmodule.partitions.partitions import Group, UserPartition -class MasqueradeTestCase(ModuleStoreTestCase, LoginEnrollmentTestCase): +class MasqueradeTestCase(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Base class for masquerade tests that sets up a test course and enrolls a user in the course. """ - def setUp(self): - super(MasqueradeTestCase, self).setUp() - - # By default, tests run with DISABLE_START_DATES=True. To test that masquerading as a student is - # working properly, we must use start dates and set a start date in the past (otherwise the access - # checks exist prematurely). - self.course = CourseFactory.create(number='masquerade-test', metadata={'start': datetime.now(UTC())}) - # Creates info page and puts random data in it for specific student info page test - self.info_page = ItemFactory.create( - category="course_info", parent_location=self.course.location, + @classmethod + def setUpClass(cls): + super(MasqueradeTestCase, cls).setUpClass() + cls.course = CourseFactory.create(number='masquerade-test', metadata={'start': datetime.now(UTC())}) + cls.info_page = ItemFactory.create( + category="course_info", parent_location=cls.course.location, data="OOGIE BLOOGIE", display_name="updates" ) - self.chapter = ItemFactory.create( - parent_location=self.course.location, + cls.chapter = ItemFactory.create( + parent_location=cls.course.location, category="chapter", display_name="Test Section", ) - self.sequential_display_name = "Test Masquerade Subsection" - self.sequential = ItemFactory.create( - parent_location=self.chapter.location, + cls.sequential_display_name = "Test Masquerade Subsection" + cls.sequential = ItemFactory.create( + parent_location=cls.chapter.location, category="sequential", - display_name=self.sequential_display_name, + display_name=cls.sequential_display_name, ) - self.vertical = ItemFactory.create( - parent_location=self.sequential.location, + cls.vertical = ItemFactory.create( + parent_location=cls.sequential.location, category="vertical", display_name="Test Unit", ) @@ -69,13 +65,17 @@ def setUp(self): options=['Correct', 'Incorrect'], correct_option='Correct' ) - self.problem_display_name = "TestMasqueradeProblem" - self.problem = ItemFactory.create( - parent_location=self.vertical.location, + cls.problem_display_name = "TestMasqueradeProblem" + cls.problem = ItemFactory.create( + parent_location=cls.vertical.location, category='problem', data=problem_xml, - display_name=self.problem_display_name + display_name=cls.problem_display_name ) + + def setUp(self): + super(MasqueradeTestCase, self).setUp() + self.test_user = self.create_user() self.login(self.test_user.email, 'test') self.enroll(self.course, True) diff --git a/lms/djangoapps/courseware/tests/test_microsites.py b/lms/djangoapps/courseware/tests/test_microsites.py index 302d09898dd2..5072090c3ba0 100644 --- a/lms/djangoapps/courseware/tests/test_microsites.py +++ b/lms/djangoapps/courseware/tests/test_microsites.py @@ -11,51 +11,42 @@ from xmodule.course_module import ( CATALOG_VISIBILITY_CATALOG_AND_ABOUT, CATALOG_VISIBILITY_NONE) from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase @attr('shard_1') -class TestMicrosites(ModuleStoreTestCase, LoginEnrollmentTestCase): +class TestMicrosites(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ This is testing of the Microsite feature """ STUDENT_INFO = [('view@test.com', 'foo'), ('view2@test.com', 'foo')] - def setUp(self): - super(TestMicrosites, self).setUp() - - # use a different hostname to test Microsites since they are - # triggered on subdomain mappings - # - # NOTE: The Microsite Configuration is in lms/envs/test.py. The content for the Test Microsite is in - # test_microsites/test_microsite. - # - # IMPORTANT: For these tests to work, this domain must be defined via - # DNS configuration (either local or published) - - self.course = CourseFactory.create( + @classmethod + def setUpClass(cls): + super(TestMicrosites, cls).setUpClass() + cls.course = CourseFactory.create( display_name='Robot_Super_Course', org='TestMicrositeX', emit_signals=True, ) - self.chapter0 = ItemFactory.create(parent_location=self.course.location, + cls.chapter0 = ItemFactory.create(parent_location=cls.course.location, display_name='Overview') - self.chapter9 = ItemFactory.create(parent_location=self.course.location, + cls.chapter9 = ItemFactory.create(parent_location=cls.course.location, display_name='factory_chapter') - self.section0 = ItemFactory.create(parent_location=self.chapter0.location, + cls.section0 = ItemFactory.create(parent_location=cls.chapter0.location, display_name='Welcome') - self.section9 = ItemFactory.create(parent_location=self.chapter9.location, + cls.section9 = ItemFactory.create(parent_location=cls.chapter9.location, display_name='factory_section') - self.course_outside_microsite = CourseFactory.create( + cls.course_outside_microsite = CourseFactory.create( display_name='Robot_Course_Outside_Microsite', org='FooX', emit_signals=True, ) # have a course which explicitly sets visibility in catalog to False - self.course_hidden_visibility = CourseFactory.create( + cls.course_hidden_visibility = CourseFactory.create( display_name='Hidden_course', org='TestMicrositeX', catalog_visibility=CATALOG_VISIBILITY_NONE, @@ -63,7 +54,7 @@ def setUp(self): ) # have a course which explicitly sets visibility in catalog and about to true - self.course_with_visibility = CourseFactory.create( + cls.course_with_visibility = CourseFactory.create( display_name='visible_course', org='TestMicrositeX', course="foo", @@ -71,6 +62,9 @@ def setUp(self): emit_signals=True, ) + def setUp(self): + super(TestMicrosites, self).setUp() + def setup_users(self): # Create student accounts and activate them. for i in range(len(self.STUDENT_INFO)): diff --git a/lms/djangoapps/courseware/tests/test_middleware.py b/lms/djangoapps/courseware/tests/test_middleware.py index 63adce06848e..c895091808e9 100644 --- a/lms/djangoapps/courseware/tests/test_middleware.py +++ b/lms/djangoapps/courseware/tests/test_middleware.py @@ -10,19 +10,22 @@ import courseware.courses as courses from courseware.middleware import RedirectUnenrolledMiddleware -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @attr('shard_1') -class CoursewareMiddlewareTestCase(ModuleStoreTestCase): +class CoursewareMiddlewareTestCase(SharedModuleStoreTestCase): """Tests that courseware middleware is correctly redirected""" + @classmethod + def setUpClass(cls): + super(CoursewareMiddlewareTestCase, cls).setUpClass() + cls.course = CourseFactory.create() + def setUp(self): super(CoursewareMiddlewareTestCase, self).setUp() - self.course = CourseFactory.create() - def check_user_not_enrolled_redirect(self): """A UserNotEnrolled exception should trigger a redirect""" request = RequestFactory().get("dummy_url") diff --git a/lms/djangoapps/courseware/tests/test_module_render.py b/lms/djangoapps/courseware/tests/test_module_render.py index 81c3a976f1d1..0c1224667d73 100644 --- a/lms/djangoapps/courseware/tests/test_module_render.py +++ b/lms/djangoapps/courseware/tests/test_module_render.py @@ -45,7 +45,7 @@ from xmodule.modulestore.tests.django_utils import ( TEST_DATA_MIXED_TOY_MODULESTORE, TEST_DATA_XML_MODULESTORE, -) + SharedModuleStoreTestCase) from xmodule.lti_module import LTIDescriptor from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore.django import modulestore @@ -121,10 +121,17 @@ def set_score(self, json_data, suffix): # pylint: disable=unused-argument @attr('shard_1') @ddt.ddt -class ModuleRenderTestCase(ModuleStoreTestCase, LoginEnrollmentTestCase): +class ModuleRenderTestCase(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Tests of courseware.module_render """ + + @classmethod + def setUpClass(cls): + super(ModuleRenderTestCase, cls).setUpClass() + cls.course_key = ToyCourseFactory.create().id + cls.toy_course = modulestore().get_course(cls.course_key) + # TODO: this test relies on the specific setup of the toy course. # It should be rewritten to build the course it needs and then test that. def setUp(self): @@ -133,8 +140,6 @@ def setUp(self): """ super(ModuleRenderTestCase, self).setUp() - self.course_key = ToyCourseFactory.create().id - self.toy_course = modulestore().get_course(self.course_key) self.mock_user = UserFactory() self.mock_user.id = 1 self.request_factory = RequestFactory() @@ -401,17 +406,20 @@ def test_hash_resource(self): @attr('shard_1') -class TestHandleXBlockCallback(ModuleStoreTestCase, LoginEnrollmentTestCase): +class TestHandleXBlockCallback(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Test the handle_xblock_callback function """ + @classmethod + def setUpClass(cls): + super(TestHandleXBlockCallback, cls).setUpClass() + cls.course_key = ToyCourseFactory.create().id + cls.toy_course = modulestore().get_course(cls.course_key) def setUp(self): super(TestHandleXBlockCallback, self).setUp() - self.course_key = ToyCourseFactory.create().id self.location = self.course_key.make_usage_key('chapter', 'Overview') - self.toy_course = modulestore().get_course(self.course_key) self.mock_user = UserFactory.create() self.request_factory = RequestFactory() @@ -709,19 +717,24 @@ def test_toc_toy_from_section(self, default_ms, setup_finds, setup_sends, toc_fi @attr('shard_1') @ddt.ddt @patch.dict('django.conf.settings.FEATURES', {'ENABLE_SPECIAL_EXAMS': True}) -class TestProctoringRendering(ModuleStoreTestCase): +class TestProctoringRendering(SharedModuleStoreTestCase): + @classmethod + def setUpClass(cls): + super(TestProctoringRendering, cls).setUpClass() + cls.course_key = ToyCourseFactory.create().id + """Check the Table of Contents for a course""" def setUp(self): """ Set up the initial mongo datastores """ super(TestProctoringRendering, self).setUp() - self.course_key = ToyCourseFactory.create().id self.chapter = 'Overview' chapter_url = '%s/%s/%s' % ('/courses', self.course_key, self.chapter) factory = RequestFactory() self.request = factory.get(chapter_url) - self.request.user = UserFactory() + self.request.user = UserFactory.create() + self.user = UserFactory.create() self.modulestore = self.store._get_modulestore_for_courselike(self.course_key) # pylint: disable=protected-access with self.modulestore.bulk_operations(self.course_key): self.toy_course = self.store.get_course(self.course_key, depth=2) @@ -1028,7 +1041,15 @@ def _find_section(self, toc, chapter_url_name, section_url_name): @attr('shard_1') -class TestGatedSubsectionRendering(ModuleStoreTestCase, MilestonesTestCaseMixin): +class TestGatedSubsectionRendering(SharedModuleStoreTestCase, MilestonesTestCaseMixin): + @classmethod + def setUpClass(cls): + super(TestGatedSubsectionRendering, cls).setUpClass() + cls.course = CourseFactory.create() + cls.course.enable_subsection_gating = True + cls.course.save() + cls.store.update_item(cls.course, 0) + """ Test the toc for a course is rendered correctly when there is gated content """ @@ -1038,10 +1059,6 @@ def setUp(self): """ super(TestGatedSubsectionRendering, self).setUp() - self.course = CourseFactory.create() - self.course.enable_subsection_gating = True - self.course.save() - self.store.update_item(self.course, 0) self.chapter = ItemFactory.create( parent=self.course, category="chapter", @@ -1113,11 +1130,10 @@ class TestHtmlModifiers(ModuleStoreTestCase): """ def setUp(self): super(TestHtmlModifiers, self).setUp() - self.user = UserFactory.create() + self.course = CourseFactory.create() self.request = RequestFactory().get('/') self.request.user = self.user self.request.session = {} - self.course = CourseFactory.create() self.content_string = '

This is the content

' self.rewrite_link = 'Test rewrite' self.rewrite_bad_link = '' @@ -1447,16 +1463,20 @@ def student_view(self, context=None): # pylint: disable=unused-argument @attr('shard_1') @patch.dict('django.conf.settings.FEATURES', {'DISPLAY_DEBUG_INFO_TO_STAFF': True, 'DISPLAY_HISTOGRAMS_TO_STAFF': True}) @patch('courseware.module_render.has_access', Mock(return_value=True, autospec=True)) -class TestStaffDebugInfo(ModuleStoreTestCase): +class TestStaffDebugInfo(SharedModuleStoreTestCase): """Tests to verify that Staff Debug Info panel and histograms are displayed to staff.""" + @classmethod + def setUpClass(cls): + super(TestStaffDebugInfo, cls).setUpClass() + cls.course = CourseFactory.create() + def setUp(self): super(TestStaffDebugInfo, self).setUp() self.user = UserFactory.create() self.request = RequestFactory().get('/') self.request.user = self.user self.request.session = {} - self.course = CourseFactory.create() problem_xml = OptionResponseXMLFactory().build_xml( question_text='The correct answer is Correct', @@ -1589,16 +1609,20 @@ def test_histogram_enabled_for_scored_xmodules(self): @attr('shard_1') @ddt.ddt -class TestAnonymousStudentId(ModuleStoreTestCase, LoginEnrollmentTestCase): +class TestAnonymousStudentId(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Test that anonymous_student_id is set correctly across a variety of XBlock types """ + @classmethod + def setUpClass(cls): + super(TestAnonymousStudentId, cls).setUpClass() + cls.course_key = ToyCourseFactory.create().id + cls.course = modulestore().get_course(cls.course_key) + def setUp(self): - super(TestAnonymousStudentId, self).setUp(create_user=False) + super(TestAnonymousStudentId, self).setUp() self.user = UserFactory() - self.course_key = ToyCourseFactory.create().id - self.course = modulestore().get_course(self.course_key) @patch('courseware.module_render.has_access', Mock(return_value=True, autospec=True)) def _get_anonymous_id(self, course_id, xblock_class): @@ -1668,11 +1692,16 @@ def test_per_course_anonymized_id(self, descriptor_class): @attr('shard_1') @patch('track.views.tracker', autospec=True) -class TestModuleTrackingContext(ModuleStoreTestCase): +class TestModuleTrackingContext(SharedModuleStoreTestCase): """ Ensure correct tracking information is included in events emitted during XBlock callback handling. """ + @classmethod + def setUpClass(cls): + super(TestModuleTrackingContext, cls).setUpClass() + cls.course = CourseFactory.create() + def setUp(self): super(TestModuleTrackingContext, self).setUp() @@ -1926,10 +1955,16 @@ def test_event_publishing(self, block_type, mock_track_function): @attr('shard_1') @ddt.ddt -class LMSXBlockServiceBindingTest(ModuleStoreTestCase): +class LMSXBlockServiceBindingTest(SharedModuleStoreTestCase): """ Tests that the LMS Module System (XBlock Runtime) provides an expected set of services. """ + + @classmethod + def setUpClass(cls): + super(LMSXBlockServiceBindingTest, cls).setUpClass() + cls.course = CourseFactory.create() + def setUp(self): """ Set up the user and other fields that will be used to instantiate the runtime. @@ -1937,7 +1972,6 @@ def setUp(self): super(LMSXBlockServiceBindingTest, self).setUp() self.user = UserFactory() self.student_data = Mock() - self.course = CourseFactory.create() self.track_function = Mock() self.xqueue_callback_url_prefix = Mock() self.request_token = Mock() @@ -2012,16 +2046,21 @@ class EmptyXModuleDescriptorWithChildren(EmptyXModuleDescriptor): # pylint: dis @attr('shard_1') @ddt.ddt -class TestFilteredChildren(ModuleStoreTestCase): +class TestFilteredChildren(SharedModuleStoreTestCase): """ Tests that verify access to XBlock/XModule children work correctly even when those children are filtered by the runtime when loaded. """ + + @classmethod + def setUpClass(cls): + super(TestFilteredChildren, cls).setUpClass() + cls.course = CourseFactory.create() + # pylint: disable=attribute-defined-outside-init, no-member def setUp(self): super(TestFilteredChildren, self).setUp() self.users = {number: UserFactory() for number in USER_NUMBERS} - self.course = CourseFactory() self._old_has_access = render.has_access patcher = patch('courseware.module_render.has_access', self._has_access) diff --git a/lms/djangoapps/courseware/tests/test_navigation.py b/lms/djangoapps/courseware/tests/test_navigation.py index d9da282c7f2a..2db5f51981f4 100644 --- a/lms/djangoapps/courseware/tests/test_navigation.py +++ b/lms/djangoapps/courseware/tests/test_navigation.py @@ -11,56 +11,60 @@ from courseware.tests.helpers import LoginEnrollmentTestCase from courseware.tests.factories import GlobalStaffFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.modulestore.django import modulestore @attr('shard_1') -class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase): +class TestNavigation(SharedModuleStoreTestCase, LoginEnrollmentTestCase): """ Check that navigation state is saved properly. """ STUDENT_INFO = [('view@test.com', 'foo'), ('view2@test.com', 'foo')] - def setUp(self): - super(TestNavigation, self).setUp() - self.test_course = CourseFactory.create() - self.course = CourseFactory.create() - self.chapter0 = ItemFactory.create(parent=self.course, + @classmethod + def setUpClass(cls): + super(TestNavigation, cls).setUpClass() + cls.test_course = CourseFactory.create() + cls.course = CourseFactory.create() + cls.chapter0 = ItemFactory.create(parent=cls.course, display_name='Overview') - self.chapter9 = ItemFactory.create(parent=self.course, + cls.chapter9 = ItemFactory.create(parent=cls.course, display_name='factory_chapter') - self.section0 = ItemFactory.create(parent=self.chapter0, + cls.section0 = ItemFactory.create(parent=cls.chapter0, display_name='Welcome') - self.section9 = ItemFactory.create(parent=self.chapter9, + cls.section9 = ItemFactory.create(parent=cls.chapter9, display_name='factory_section') - self.unit0 = ItemFactory.create(parent=self.section0, + cls.unit0 = ItemFactory.create(parent=cls.section0, display_name='New Unit') - self.chapterchrome = ItemFactory.create(parent=self.course, + cls.chapterchrome = ItemFactory.create(parent=cls.course, display_name='Chrome') - self.chromelesssection = ItemFactory.create(parent=self.chapterchrome, + cls.chromelesssection = ItemFactory.create(parent=cls.chapterchrome, display_name='chromeless', chrome='none') - self.accordionsection = ItemFactory.create(parent=self.chapterchrome, + cls.accordionsection = ItemFactory.create(parent=cls.chapterchrome, display_name='accordion', chrome='accordion') - self.tabssection = ItemFactory.create(parent=self.chapterchrome, + cls.tabssection = ItemFactory.create(parent=cls.chapterchrome, display_name='tabs', chrome='tabs') - self.defaultchromesection = ItemFactory.create( - parent=self.chapterchrome, + cls.defaultchromesection = ItemFactory.create( + parent=cls.chapterchrome, display_name='defaultchrome', ) - self.fullchromesection = ItemFactory.create(parent=self.chapterchrome, + cls.fullchromesection = ItemFactory.create(parent=cls.chapterchrome, display_name='fullchrome', chrome='accordion,tabs') - self.tabtest = ItemFactory.create(parent=self.chapterchrome, + cls.tabtest = ItemFactory.create(parent=cls.chapterchrome, display_name='progress_tab', default_tab='progress') + def setUp(self): + super(TestNavigation, self).setUp() + # Create student accounts and activate them. for i in range(len(self.STUDENT_INFO)): email, password = self.STUDENT_INFO[i] diff --git a/lms/djangoapps/courseware/tests/test_split_module.py b/lms/djangoapps/courseware/tests/test_split_module.py index d6002bad35ce..da87ba1aa4af 100644 --- a/lms/djangoapps/courseware/tests/test_split_module.py +++ b/lms/djangoapps/courseware/tests/test_split_module.py @@ -9,13 +9,13 @@ from courseware.model_data import FieldDataCache from student.tests.factories import UserFactory, CourseEnrollmentFactory from xmodule.modulestore.tests.factories import ItemFactory, CourseFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.partitions.partitions import Group, UserPartition from openedx.core.djangoapps.user_api.tests.factories import UserCourseTagFactory @attr('shard_1') -class SplitTestBase(ModuleStoreTestCase): +class SplitTestBase(SharedModuleStoreTestCase): """ Sets up a basic course and user for split test testing. Also provides tests of rendered HTML for two user_tag conditions, 0 and 1. @@ -27,9 +27,10 @@ class SplitTestBase(ModuleStoreTestCase): HIDDEN_CONTENT = None VISIBLE_CONTENT = None - def setUp(self): - super(SplitTestBase, self).setUp() - self.partition = UserPartition( + @classmethod + def setUpClass(cls): + super(SplitTestBase, cls).setUpClass() + cls.partition = UserPartition( 0, 'first_partition', 'First Partition', @@ -39,22 +40,25 @@ def setUp(self): ] ) - self.course = CourseFactory.create( - number=self.COURSE_NUMBER, - user_partitions=[self.partition] + cls.course = CourseFactory.create( + number=cls.COURSE_NUMBER, + user_partitions=[cls.partition] ) - self.chapter = ItemFactory.create( - parent_location=self.course.location, + cls.chapter = ItemFactory.create( + parent_location=cls.course.location, category="chapter", display_name="test chapter", ) - self.sequential = ItemFactory.create( - parent_location=self.chapter.location, + cls.sequential = ItemFactory.create( + parent_location=cls.chapter.location, category="sequential", display_name="Split Test Tests", ) + def setUp(self): + super(SplitTestBase, self).setUp() + self.student = UserFactory.create() CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) self.client.login(username=self.student.username, password='test') @@ -269,14 +273,14 @@ def setUp(self): @attr('shard_1') -class SplitTestPosition(ModuleStoreTestCase): +class SplitTestPosition(SharedModuleStoreTestCase): """ Check that we can change positions in a course with partitions defined """ - def setUp(self): - super(SplitTestPosition, self).setUp() - - self.partition = UserPartition( + @classmethod + def setUpClass(cls): + super(SplitTestPosition, cls).setUpClass() + cls.partition = UserPartition( 0, 'first_partition', 'First Partition', @@ -286,16 +290,19 @@ def setUp(self): ] ) - self.course = CourseFactory.create( - user_partitions=[self.partition] + cls.course = CourseFactory.create( + user_partitions=[cls.partition] ) - self.chapter = ItemFactory.create( - parent_location=self.course.location, + cls.chapter = ItemFactory.create( + parent_location=cls.course.location, category="chapter", display_name="test chapter", ) + def setUp(self): + super(SplitTestPosition, self).setUp() + self.student = UserFactory.create() CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) self.client.login(username=self.student.username, password='test') diff --git a/lms/djangoapps/courseware/tests/test_submitting_problems.py b/lms/djangoapps/courseware/tests/test_submitting_problems.py index 031467a91fdd..7eb36effdaca 100644 --- a/lms/djangoapps/courseware/tests/test_submitting_problems.py +++ b/lms/djangoapps/courseware/tests/test_submitting_problems.py @@ -24,7 +24,7 @@ from lms.djangoapps.lms_xblock.runtime import quote_slashes from student.tests.factories import UserFactory from student.models import anonymous_id_for_user -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory from xmodule.partitions.partitions import Group, UserPartition from openedx.core.djangoapps.credit.api import ( @@ -126,13 +126,10 @@ class TestSubmittingProblems(ModuleStoreTestCase, LoginEnrollmentTestCase, Probl COURSE_NAME = "test_course" def setUp(self): - - super(TestSubmittingProblems, self).setUp(create_user=False) - # Create course - self.course = CourseFactory.create(display_name=self.COURSE_NAME, number=self.COURSE_SLUG) - assert self.course, "Couldn't load course %r" % self.COURSE_NAME + super(TestSubmittingProblems, self).setUp() # create a test student + self.course = CourseFactory.create(display_name=self.COURSE_NAME, number=self.COURSE_SLUG) self.student = 'view@test.com' self.password = 'foo' self.create_account('u1', self.student, self.password) diff --git a/lms/djangoapps/courseware/tests/test_tabs.py b/lms/djangoapps/courseware/tests/test_tabs.py index 70c6d498585d..4d8b7f8d68d7 100644 --- a/lms/djangoapps/courseware/tests/test_tabs.py +++ b/lms/djangoapps/courseware/tests/test_tabs.py @@ -28,21 +28,25 @@ from milestones.tests.utils import MilestonesTestCaseMixin from xmodule import tabs as xmodule_tabs from xmodule.modulestore.tests.django_utils import ( - TEST_DATA_MIXED_TOY_MODULESTORE, TEST_DATA_MIXED_CLOSED_MODULESTORE -) + TEST_DATA_MIXED_TOY_MODULESTORE, TEST_DATA_MIXED_CLOSED_MODULESTORE, + SharedModuleStoreTestCase) from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory -class TabTestCase(ModuleStoreTestCase): +class TabTestCase(SharedModuleStoreTestCase): """Base class for Tab-related test cases.""" + @classmethod + def setUpClass(cls): + super(TabTestCase, cls).setUpClass() + + cls.course = CourseFactory.create(org='edX', course='toy', run='2012_Fall') + cls.fake_dict_tab = {'fake_key': 'fake_value'} + cls.books = None + def setUp(self): super(TabTestCase, self).setUp() - - self.course = CourseFactory.create(org='edX', course='toy', run='2012_Fall') - self.fake_dict_tab = {'fake_key': 'fake_value'} self.reverse = lambda name, args: "name/{0}/args/{1}".format(name, ",".join(str(a) for a in args)) - self.books = None def create_mock_user(self, is_authenticated=True, is_staff=True, is_enrolled=True): """ @@ -219,21 +223,25 @@ def test_textbooks_enabled(self): @attr('shard_1') -class StaticTabDateTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase): +class StaticTabDateTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase): """Test cases for Static Tab Dates.""" MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE - def setUp(self): - super(StaticTabDateTestCase, self).setUp() - self.course = CourseFactory.create() - self.page = ItemFactory.create( - category="static_tab", parent_location=self.course.location, + @classmethod + def setUpClass(cls): + super(StaticTabDateTestCase, cls).setUpClass() + cls.course = CourseFactory.create() + cls.page = ItemFactory.create( + category="static_tab", parent_location=cls.course.location, data="OOGIE BLOOGIE", display_name="new_tab" ) - self.course.tabs.append(xmodule_tabs.CourseTab.load('static_tab', name='New Tab', url_slug='new_tab')) - self.course.save() - self.toy_course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall') + cls.course.tabs.append(xmodule_tabs.CourseTab.load('static_tab', name='New Tab', url_slug='new_tab')) + cls.course.save() + cls.toy_course_key = SlashSeparatedCourseKey('edX', 'toy', '2012_Fall') + + def setUp(self): + super(StaticTabDateTestCase, self).setUp() def test_logged_in(self): self.setup_user() @@ -417,16 +425,20 @@ def test_course_tabs_list_for_staff_members(self): @attr('shard_1') -class TextBookCourseViewsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase): +class TextBookCourseViewsTestCase(LoginEnrollmentTestCase, SharedModuleStoreTestCase): """ Validate tab behavior when dealing with textbooks. """ MODULESTORE = TEST_DATA_MIXED_TOY_MODULESTORE + @classmethod + def setUpClass(cls): + super(TextBookCourseViewsTestCase, cls).setUpClass() + cls.course = CourseFactory.create() + def setUp(self): super(TextBookCourseViewsTestCase, self).setUp() - self.course = CourseFactory.create() self.set_up_books(2) self.setup_user() self.enroll(self.course) From 6a6ef0fd35e8deb7e672803573551646f252b30d Mon Sep 17 00:00:00 2001 From: Toby Lawrence Date: Fri, 5 Feb 2016 13:43:36 -0500 Subject: [PATCH 03/60] Fix some broken tests. --- .../courseware/tests/test_navigation.py | 41 +++++++++---------- .../tests/test_partition_scheme.py | 2 +- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/lms/djangoapps/courseware/tests/test_navigation.py b/lms/djangoapps/courseware/tests/test_navigation.py index 2db5f51981f4..c02aafe0f2bf 100644 --- a/lms/djangoapps/courseware/tests/test_navigation.py +++ b/lms/djangoapps/courseware/tests/test_navigation.py @@ -17,54 +17,51 @@ @attr('shard_1') -class TestNavigation(SharedModuleStoreTestCase, LoginEnrollmentTestCase): +class TestNavigation(ModuleStoreTestCase, LoginEnrollmentTestCase): """ Check that navigation state is saved properly. """ STUDENT_INFO = [('view@test.com', 'foo'), ('view2@test.com', 'foo')] - @classmethod - def setUpClass(cls): - super(TestNavigation, cls).setUpClass() - cls.test_course = CourseFactory.create() - cls.course = CourseFactory.create() - cls.chapter0 = ItemFactory.create(parent=cls.course, + def setUp(self): + super(TestNavigation, self).setUp() + + self.test_course = CourseFactory.create() + self.course = CourseFactory.create() + self.chapter0 = ItemFactory.create(parent=self.course, display_name='Overview') - cls.chapter9 = ItemFactory.create(parent=cls.course, + self.chapter9 = ItemFactory.create(parent=self.course, display_name='factory_chapter') - cls.section0 = ItemFactory.create(parent=cls.chapter0, + self.section0 = ItemFactory.create(parent=self.chapter0, display_name='Welcome') - cls.section9 = ItemFactory.create(parent=cls.chapter9, + self.section9 = ItemFactory.create(parent=self.chapter9, display_name='factory_section') - cls.unit0 = ItemFactory.create(parent=cls.section0, + self.unit0 = ItemFactory.create(parent=self.section0, display_name='New Unit') - cls.chapterchrome = ItemFactory.create(parent=cls.course, + self.chapterchrome = ItemFactory.create(parent=self.course, display_name='Chrome') - cls.chromelesssection = ItemFactory.create(parent=cls.chapterchrome, + self.chromelesssection = ItemFactory.create(parent=self.chapterchrome, display_name='chromeless', chrome='none') - cls.accordionsection = ItemFactory.create(parent=cls.chapterchrome, + self.accordionsection = ItemFactory.create(parent=self.chapterchrome, display_name='accordion', chrome='accordion') - cls.tabssection = ItemFactory.create(parent=cls.chapterchrome, + self.tabssection = ItemFactory.create(parent=self.chapterchrome, display_name='tabs', chrome='tabs') - cls.defaultchromesection = ItemFactory.create( - parent=cls.chapterchrome, + self.defaultchromesection = ItemFactory.create( + parent=self.chapterchrome, display_name='defaultchrome', ) - cls.fullchromesection = ItemFactory.create(parent=cls.chapterchrome, + self.fullchromesection = ItemFactory.create(parent=self.chapterchrome, display_name='fullchrome', chrome='accordion,tabs') - cls.tabtest = ItemFactory.create(parent=cls.chapterchrome, + self.tabtest = ItemFactory.create(parent=self.chapterchrome, display_name='progress_tab', default_tab='progress') - def setUp(self): - super(TestNavigation, self).setUp() - # Create student accounts and activate them. for i in range(len(self.STUDENT_INFO)): email, password = self.STUDENT_INFO[i] diff --git a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py index f53708e31491..35d66bb1d959 100644 --- a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py +++ b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py @@ -393,7 +393,7 @@ def test_group_masquerade_with_cohort(self): group. """ self.course.cohort_config = {'cohorted': True} - self.update_course(self.course, self.test_user.id) + modulestore().update_item(self.course, self.test_user.id) cohort = CohortFactory.create(course_id=self.course.id, users=[self.test_user]) CourseUserGroupPartitionGroup( course_user_group=cohort, From e2ed8ff787f9960ffedf4de0772b0f2b1f5daf61 Mon Sep 17 00:00:00 2001 From: Toby Lawrence Date: Wed, 3 Feb 2016 11:17:46 -0500 Subject: [PATCH 04/60] Switch to SharedModuleStoreTestCase in the 'student' app where possible. --- .../student/tests/test_admin_views.py | 10 ++++++--- .../student/tests/test_bulk_email_settings.py | 12 ++++++----- .../student/tests/test_certificates.py | 18 ++++++++++------ .../student/tests/test_enrollment.py | 9 ++++++-- .../tests/test_login_registration_forms.py | 21 +++++++++++++------ .../djangoapps/student/tests/test_refunds.py | 6 +++++- common/djangoapps/student/tests/test_views.py | 10 ++++++--- 7 files changed, 60 insertions(+), 26 deletions(-) diff --git a/common/djangoapps/student/tests/test_admin_views.py b/common/djangoapps/student/tests/test_admin_views.py index 910bfe474e9b..411b9a4e4792 100644 --- a/common/djangoapps/student/tests/test_admin_views.py +++ b/common/djangoapps/student/tests/test_admin_views.py @@ -3,19 +3,23 @@ """ from django.core.urlresolvers import reverse -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from student.tests.factories import UserFactory -class AdminCourseRolesPageTest(ModuleStoreTestCase): +class AdminCourseRolesPageTest(SharedModuleStoreTestCase): """Test the django admin course roles form saving data in db. """ + @classmethod + def setUpClass(cls): + super(AdminCourseRolesPageTest, cls).setUpClass() + cls.course = CourseFactory.create(org='edx') + def setUp(self): super(AdminCourseRolesPageTest, self).setUp() self.user = UserFactory.create(is_staff=True, is_superuser=True) self.user.save() - self.course = CourseFactory.create(org='edx') def test_save_valid_data(self): diff --git a/common/djangoapps/student/tests/test_bulk_email_settings.py b/common/djangoapps/student/tests/test_bulk_email_settings.py index 4db331183e34..522064df90d4 100644 --- a/common/djangoapps/student/tests/test_bulk_email_settings.py +++ b/common/djangoapps/student/tests/test_bulk_email_settings.py @@ -12,7 +12,7 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey from student.tests.factories import UserFactory, CourseEnrollmentFactory -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.django_utils import TEST_DATA_MIXED_TOY_MODULESTORE from xmodule.modulestore.tests.factories import CourseFactory @@ -22,16 +22,18 @@ @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') -class TestStudentDashboardEmailView(ModuleStoreTestCase): +class TestStudentDashboardEmailView(SharedModuleStoreTestCase): """ Check for email view displayed with flag """ + @classmethod + def setUpClass(cls): + super(TestStudentDashboardEmailView, cls).setUpClass() + cls.course = CourseFactory.create() def setUp(self): super(TestStudentDashboardEmailView, self).setUp() - self.course = CourseFactory.create() - # Create student account student = UserFactory.create() CourseEnrollmentFactory.create(user=student, course_id=self.course.id) @@ -84,7 +86,7 @@ def test_email_authorized(self): @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') -class TestStudentDashboardEmailViewXMLBacked(ModuleStoreTestCase): +class TestStudentDashboardEmailViewXMLBacked(SharedModuleStoreTestCase): """ Check for email view on student dashboard, with XML backed course. """ diff --git a/common/djangoapps/student/tests/test_certificates.py b/common/djangoapps/student/tests/test_certificates.py index 321cc74d903b..711fa6e56371 100644 --- a/common/djangoapps/student/tests/test_certificates.py +++ b/common/djangoapps/student/tests/test_certificates.py @@ -8,8 +8,9 @@ from django.core.urlresolvers import reverse from mock import patch from django.test.utils import override_settings +from xmodule.modulestore import ModuleStoreEnum -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory from certificates.tests.factories import GeneratedCertificateFactory # pylint: disable=import-error @@ -30,23 +31,28 @@ def _fake_is_request_in_microsite(): @ddt.ddt @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') -class CertificateDisplayTest(ModuleStoreTestCase): +class CertificateDisplayTest(SharedModuleStoreTestCase): """Tests display of certificates on the student dashboard. """ USERNAME = "test_user" PASSWORD = "password" DOWNLOAD_URL = "http://www.example.com/certificate.pdf" + @classmethod + def setUpClass(cls): + super(CertificateDisplayTest, cls).setUpClass() + cls.course = CourseFactory() + cls.course.certificates_display_behavior = "early_with_info" + + with cls.store.branch_setting(ModuleStoreEnum.Branch.draft_preferred, cls.course.id): + cls.store.update_item(cls.course, cls.USERNAME) + def setUp(self): super(CertificateDisplayTest, self).setUp() self.user = UserFactory.create(username=self.USERNAME, password=self.PASSWORD) result = self.client.login(username=self.USERNAME, password=self.PASSWORD) self.assertTrue(result, msg="Could not log in") - self.course = CourseFactory() - self.course.certificates_display_behavior = "early_with_info" - self.update_course(self.course, self.user.username) - @ddt.data('verified', 'professional') @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False}) def test_display_verified_certificate(self, enrollment_mode): diff --git a/common/djangoapps/student/tests/test_enrollment.py b/common/djangoapps/student/tests/test_enrollment.py index 679a86e12bd3..a6815285eb38 100644 --- a/common/djangoapps/student/tests/test_enrollment.py +++ b/common/djangoapps/student/tests/test_enrollment.py @@ -8,7 +8,7 @@ from django.conf import settings from django.core.urlresolvers import reverse from course_modes.models import CourseMode -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory from util.testing import UrlResetMixin from embargo.test_utils import restrict_course @@ -18,7 +18,7 @@ @ddt.ddt @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') -class EnrollmentTest(UrlResetMixin, ModuleStoreTestCase): +class EnrollmentTest(UrlResetMixin, SharedModuleStoreTestCase): """ Test student enrollment, especially with different course modes. """ @@ -27,6 +27,11 @@ class EnrollmentTest(UrlResetMixin, ModuleStoreTestCase): EMAIL = "bob@example.com" PASSWORD = "edx" + @classmethod + def setUpClass(cls): + super(EnrollmentTest, cls).setUpClass() + cls.course = CourseFactory.create() + @patch.dict(settings.FEATURES, {'EMBARGO': True}) def setUp(self): """ Create a course and user, then log in. """ diff --git a/common/djangoapps/student/tests/test_login_registration_forms.py b/common/djangoapps/student/tests/test_login_registration_forms.py index a17161ed0ab9..f0f338721d4d 100644 --- a/common/djangoapps/student/tests/test_login_registration_forms.py +++ b/common/djangoapps/student/tests/test_login_registration_forms.py @@ -10,8 +10,7 @@ from util.testing import UrlResetMixin from xmodule.modulestore.tests.factories import CourseFactory from third_party_auth.tests.testutil import ThirdPartyAuthTestMixin -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase - +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase # This relies on third party auth being enabled in the test # settings with the feature flag `ENABLE_THIRD_PARTY_AUTH` @@ -38,14 +37,19 @@ def _finish_auth_url(params): @ddt.ddt @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') -class LoginFormTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleStoreTestCase): +class LoginFormTest(ThirdPartyAuthTestMixin, UrlResetMixin, SharedModuleStoreTestCase): """Test rendering of the login form. """ + + @classmethod + def setUpClass(cls): + super(LoginFormTest, cls).setUpClass() + cls.course = CourseFactory.create() + @patch.dict(settings.FEATURES, {"ENABLE_COMBINED_LOGIN_REGISTRATION": False}) def setUp(self): super(LoginFormTest, self).setUp('lms.urls') self.url = reverse("signin_user") - self.course = CourseFactory.create() self.course_id = unicode(self.course.id) self.courseware_url = reverse("courseware", args=[self.course_id]) self.configure_google_provider(enabled=True) @@ -148,14 +152,19 @@ def test_params(self, opt_in_value): @ddt.ddt @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') -class RegisterFormTest(ThirdPartyAuthTestMixin, UrlResetMixin, ModuleStoreTestCase): +class RegisterFormTest(ThirdPartyAuthTestMixin, UrlResetMixin, SharedModuleStoreTestCase): """Test rendering of the registration form. """ + + @classmethod + def setUpClass(cls): + super(RegisterFormTest, cls).setUpClass() + cls.course = CourseFactory.create() + @patch.dict(settings.FEATURES, {"ENABLE_COMBINED_LOGIN_REGISTRATION": False}) def setUp(self): super(RegisterFormTest, self).setUp('lms.urls') self.url = reverse("register_user") - self.course = CourseFactory.create() self.course_id = unicode(self.course.id) self.configure_google_provider(enabled=True) self.configure_facebook_provider(enabled=True) diff --git a/common/djangoapps/student/tests/test_refunds.py b/common/djangoapps/student/tests/test_refunds.py index 2b31d758fa36..330be06ad09a 100644 --- a/common/djangoapps/student/tests/test_refunds.py +++ b/common/djangoapps/student/tests/test_refunds.py @@ -41,10 +41,14 @@ class RefundableTest(SharedModuleStoreTestCase): Tests for dashboard utility functions """ + @classmethod + def setUpClass(cls): + super(RefundableTest, cls).setUpClass() + cls.course = CourseFactory.create() + def setUp(self): """ Setup components used by each refund test.""" super(RefundableTest, self).setUp() - self.course = CourseFactory.create() self.user = UserFactory.create(username="jack", email="jack@fake.edx.org", password='test') self.verified_mode = CourseModeFactory.create( course_id=self.course.id, diff --git a/common/djangoapps/student/tests/test_views.py b/common/djangoapps/student/tests/test_views.py index a321e3528326..38a72d30fa45 100644 --- a/common/djangoapps/student/tests/test_views.py +++ b/common/djangoapps/student/tests/test_views.py @@ -12,13 +12,13 @@ from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.models import CourseEnrollment from student.helpers import DISABLE_UNENROLL_CERT_STATES -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase +from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import CourseFactory @ddt.ddt @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') -class TestStudentDashboardUnenrollments(ModuleStoreTestCase): +class TestStudentDashboardUnenrollments(SharedModuleStoreTestCase): """ Test to ensure that the student dashboard does not show the unenroll button for users with certificates. """ @@ -27,10 +27,14 @@ class TestStudentDashboardUnenrollments(ModuleStoreTestCase): PASSWORD = "edx" UNENROLL_ELEMENT_ID = "#actions-item-unenroll-0" + @classmethod + def setUpClass(cls): + super(TestStudentDashboardUnenrollments, cls).setUpClass() + cls.course = CourseFactory.create() + def setUp(self): """ Create a course and user, then log in. """ super(TestStudentDashboardUnenrollments, self).setUp() - self.course = CourseFactory.create() self.user = UserFactory.create(username=self.USERNAME, email=self.EMAIL, password=self.PASSWORD) CourseEnrollmentFactory(course_id=self.course.id, user=self.user) self.cert_status = None From 982c3e623bdfefbb5155866a121c01898532dbc2 Mon Sep 17 00:00:00 2001 From: Sven Marnach Date: Thu, 4 Feb 2016 23:31:38 +0100 Subject: [PATCH 05/60] Pass DOM element, not jQuery object to XBlock initialisation. The function initializeXBlock() expects a DOM element, and is passed one in most cases. However, when adding a new XBlock component in Studio, the function is passed a jQuery object, which ends up being forwarded to the actual initialisation function of the XBlock. --- cms/static/js/views/xblock.js | 2 +- cms/static/js/xblock/authoring.js | 17 +++++++++-------- .../lib/xmodule/xmodule/js/src/html/edit.coffee | 2 +- .../xmodule/xmodule/js/src/problem/edit.coffee | 2 +- .../xmodule/js/src/tabs/tabs-aggregator.coffee | 2 +- common/static/js/xblock/core.js | 2 +- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cms/static/js/views/xblock.js b/cms/static/js/views/xblock.js index 9a8643f58b4f..13f59922042a 100644 --- a/cms/static/js/views/xblock.js +++ b/cms/static/js/views/xblock.js @@ -43,7 +43,7 @@ define(["jquery", "underscore", "common/js/components/utils/view_utils", "js/vie fragmentsRendered.always(function() { xblockElement = self.$('.xblock').first(); try { - xblock = XBlock.initializeBlock(xblockElement); + xblock = XBlock.initializeBlock(xblockElement.get(0)); self.xblock = xblock; self.xblockReady(xblock); if (successCallback) { diff --git a/cms/static/js/xblock/authoring.js b/cms/static/js/xblock/authoring.js index d9abe7d6a6aa..40d6bd5da715 100644 --- a/cms/static/js/xblock/authoring.js +++ b/cms/static/js/xblock/authoring.js @@ -5,6 +5,7 @@ 'use strict'; function VisibilityEditorView(runtime, element) { + var $element = $(element); this.getGroupAccess = function() { var groupAccess = {}, checkboxValues, @@ -15,12 +16,12 @@ // defined by VerificationPartitionScheme on the backend! ALLOW_GROUP_ID = 1; - if (element.find('.visibility-level-all').prop('checked')) { + if ($element.find('.visibility-level-all').prop('checked')) { return {}; } // Cohort partitions (user is allowed to select more than one) - element.find('.field-visibility-content-group input:checked').each(function(index, input) { + $element.find('.field-visibility-content-group input:checked').each(function(index, input) { checkboxValues = $(input).val().split("-"); partitionId = parseInt(checkboxValues[0], 10); groupId = parseInt(checkboxValues[1], 10); @@ -33,7 +34,7 @@ }); // Verification partitions (user can select exactly one) - if (element.find('#verification-access-checkbox').prop('checked')) { + if ($element.find('#verification-access-checkbox').prop('checked')) { partitionId = parseInt($('#verification-access-dropdown').val(), 10); groupAccess[partitionId] = [ALLOW_GROUP_ID]; } @@ -42,19 +43,19 @@ }; // When selecting "all students and staff", uncheck the specific groups - element.find('.field-visibility-level input').change(function(event) { + $element.find('.field-visibility-level input').change(function(event) { if ($(event.target).hasClass('visibility-level-all')) { - element.find('.field-visibility-content-group input, .field-visibility-verification input') + $element.find('.field-visibility-content-group input, .field-visibility-verification input') .prop('checked', false); } }); // When selecting a specific group, deselect "all students and staff" and // select "specific content groups" instead.` - element.find('.field-visibility-content-group input, .field-visibility-verification input') + $element.find('.field-visibility-content-group input, .field-visibility-verification input') .change(function() { - element.find('.visibility-level-all').prop('checked', false); - element.find('.visibility-level-specific').prop('checked', true); + $element.find('.visibility-level-all').prop('checked', false); + $element.find('.visibility-level-specific').prop('checked', true); }); } diff --git a/common/lib/xmodule/xmodule/js/src/html/edit.coffee b/common/lib/xmodule/xmodule/js/src/html/edit.coffee index 4ba4f2bb54f4..a2597343044c 100644 --- a/common/lib/xmodule/xmodule/js/src/html/edit.coffee +++ b/common/lib/xmodule/xmodule/js/src/html/edit.coffee @@ -26,7 +26,7 @@ class @HTMLEditingDescriptor CUSTOM_FONTS + STANDARD_FONTS constructor: (element) -> - @element = element + @element = $(element) @base_asset_url = @element.find("#editor-tab").data('base-asset-url') @editor_choice = @element.find("#editor-tab").data('editor') if @base_asset_url == undefined diff --git a/common/lib/xmodule/xmodule/js/src/problem/edit.coffee b/common/lib/xmodule/xmodule/js/src/problem/edit.coffee index 5c2638974b45..0f0f2c1e4ed0 100644 --- a/common/lib/xmodule/xmodule/js/src/problem/edit.coffee +++ b/common/lib/xmodule/xmodule/js/src/problem/edit.coffee @@ -13,7 +13,7 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor @explanationTemplate: "[explanation]\n#{gettext 'Short explanation'}\n[explanation]\n" constructor: (element) -> - @element = element + @element = $(element) if $(".markdown-box", @element).length != 0 @markdown_editor = CodeMirror.fromTextArea($(".markdown-box", element)[0], { diff --git a/common/lib/xmodule/xmodule/js/src/tabs/tabs-aggregator.coffee b/common/lib/xmodule/xmodule/js/src/tabs/tabs-aggregator.coffee index e64d0ca84000..0afed762faf1 100644 --- a/common/lib/xmodule/xmodule/js/src/tabs/tabs-aggregator.coffee +++ b/common/lib/xmodule/xmodule/js/src/tabs/tabs-aggregator.coffee @@ -2,7 +2,7 @@ class @TabsEditingDescriptor @isInactiveClass : "is-inactive" constructor: (element) -> - @element = element; + @element = $(element) ### Not tested on syncing of multiple editors of same type in tabs (Like many CodeMirrors). diff --git a/common/static/js/xblock/core.js b/common/static/js/xblock/core.js index 1c6632c71dbe..b9f19ce4348d 100644 --- a/common/static/js/xblock/core.js +++ b/common/static/js/xblock/core.js @@ -69,7 +69,7 @@ } else { block = {}; } - block.element = element; + block.element = $element; block.name = $element.data('name'); block.type = $element.data('block-type'); $element.trigger('xblock-initialized'); From 97228f3b92bffbee570f58023a9201e31bd75ae7 Mon Sep 17 00:00:00 2001 From: Sylvia Pearce Date: Wed, 10 Feb 2016 13:26:47 -0500 Subject: [PATCH 06/60] Update help text for Pages page in Studio to reflect Courseware-Course etc change --- cms/templates/edit-tabs.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cms/templates/edit-tabs.html b/cms/templates/edit-tabs.html index 6ad7d6f4d4b8..04255d8b9bc6 100644 --- a/cms/templates/edit-tabs.html +++ b/cms/templates/edit-tabs.html @@ -140,7 +140,7 @@

${_(tab.name)}