Example #1
0
    def test_chunked_queries_send_numerous_emails(self, email_mock):
        """
        Test sending a large number of emails, to test the chunked querying
        """
        mock_factory = MockCourseEmailResult()
        email_mock.side_effect = mock_factory.get_mock_update_subtask_status()
        added_users = []
        for _ in xrange(LARGE_NUM_EMAILS):
            user = UserFactory()
            added_users.append(user)
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

        optouts = []
        for i in [1, 3, 9, 10, 18]:  # 5 random optouts
            user = added_users[i]
            optouts.append(user)
            optout = Optout(user=user, course_id=self.course.id)
            optout.save()

        test_email = {
            'action': 'Send email',
            'to_option': 'all',
            'subject': 'test subject for all',
            'message': 'test message for all'
        }
        response = self.client.post(self.url, test_email)
        self.assertContains(response, "Your email was successfully queued for sending.")
        self.assertEquals(mock_factory.emails_sent,
                          1 + len(self.staff) + len(self.students) + LARGE_NUM_EMAILS - len(optouts))
        outbox_contents = [e.to[0] for e in mail.outbox]
        should_send_contents = ([self.instructor.email] +
                                [s.email for s in self.staff] +
                                [s.email for s in self.students] +
                                [s.email for s in added_users if s not in optouts])
        self.assertItemsEqual(outbox_contents, should_send_contents)
    def test_resolve_course_enrollments(self):
        """
        Test that the CourseEnrollmentsScopeResolver actually returns all enrollments
        """

        test_user_1 = UserFactory.create(password='******')
        CourseEnrollmentFactory(user=test_user_1, course_id=self.course.id)
        test_user_2 = UserFactory.create(password='******')
        CourseEnrollmentFactory(user=test_user_2, course_id=self.course.id)
        test_user_3 = UserFactory.create(password='******')
        enrollment = CourseEnrollmentFactory(user=test_user_3, course_id=self.course.id)

        # unenroll #3

        enrollment.is_active = False
        enrollment.save()

        resolver = CourseEnrollmentsScopeResolver()

        user_ids = resolver.resolve('course_enrollments', {'course_id': self.course.id}, None)

        # should have first two, but the third should not be present

        self.assertTrue(test_user_1.id in user_ids)
        self.assertTrue(test_user_2.id in user_ids)

        self.assertFalse(test_user_3.id in user_ids)
Example #3
0
    def setUp(self):
        course_title = u"įŗ—Ć«į¹”įŗ— title ļ½²ä¹‡äø‚ļ½² ļ¾¶ä¹‡äø‚äø‚ļ¾‘g乇 ļ½·oå°ŗ ļ¾‘ļ¾šļ¾š тэѕт Š¼ŃŃ•Ń•Š°Š‘э"
        self.course = CourseFactory.create(display_name=course_title)

        self.instructor = InstructorFactory(course=self.course.location)

        # Create staff
        self.staff = [StaffFactory(course=self.course.location)
                      for _ in xrange(STAFF_COUNT)]

        # Create students
        self.students = [UserFactory() for _ in xrange(STUDENT_COUNT)]
        for student in self.students:
            CourseEnrollmentFactory.create(user=student, course_id=self.course.id)

        # load initial content (since we don't run migrations as part of tests):
        call_command("loaddata", "course_email_template.json")

        self.client.login(username=self.instructor.username, password="******")

        # Pull up email view on instructor dashboard
        self.url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id})
        response = self.client.get(self.url)
        email_link = '<a href="#" onclick="goto(\'Email\')" class="None">Email</a>'
        # If this fails, it is likely because ENABLE_INSTRUCTOR_EMAIL is set to False
        self.assertTrue(email_link in response.content)

        # Select the Email view of the instructor dash
        session = self.client.session
        session['idash_mode'] = 'Email'
        session.save()
        response = self.client.get(self.url)
        selected_email_link = '<a href="#" onclick="goto(\'Email\')" class="selectedmode">Email</a>'
        self.assertTrue(selected_email_link in response.content)
Example #4
0
    def setUp(self):
        super(TestBlockListGetForm, self).setUp()

        self.student = UserFactory.create()
        self.student2 = UserFactory.create()
        self.staff = UserFactory.create(is_staff=True)

        CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
        CourseEnrollmentFactory.create(user=self.student2, course_id=self.course.id)

        usage_key = self.course.location
        self.initial = {'requesting_user': self.student}
        self.form_data = QueryDict(
            urlencode({
                'username': self.student.username,
                'usage_key': unicode(usage_key),
            }),
            mutable=True,
        )
        self.cleaned_data = {
            'all_blocks': None,
            'block_counts': set(),
            'depth': 0,
            'nav_depth': None,
            'return_type': 'dict',
            'requested_fields': {'display_name', 'type'},
            'student_view_data': set(),
            'usage_key': usage_key,
            'username': self.student.username,
            'user': self.student,
        }
Example #5
0
def setup_students_and_grades(context):
    """
    Create students and set their grades.
    :param context:  class reference
    """
    if context.course:
        context.student = student = UserFactory.create()
        CourseEnrollmentFactory.create(user=student, course_id=context.course.id)

        context.student2 = student2 = UserFactory.create()
        CourseEnrollmentFactory.create(user=student2, course_id=context.course.id)

        # create grades for self.student as if they'd submitted the ccx
        for chapter in context.course.get_children():
            for i, section in enumerate(chapter.get_children()):
                for j, problem in enumerate(section.get_children()):
                    # if not problem.visible_to_staff_only:
                    StudentModuleFactory.create(
                        grade=1 if i < j else 0,
                        max_grade=1,
                        student=context.student,
                        course_id=context.course.id,
                        module_state_key=problem.location
                    )

                    StudentModuleFactory.create(
                        grade=1 if i > j else 0,
                        max_grade=1,
                        student=context.student2,
                        course_id=context.course.id,
                        module_state_key=problem.location
                    )
    def test_masquerade_expired(self, mock_get_course_run_details):
        mock_get_course_run_details.return_value = {'weeks_to_complete': 1}

        audit_student = UserFactory(username='******')
        enrollment = CourseEnrollmentFactory.create(
            user=audit_student,
            course_id=self.course.id,
            mode='audit',
        )
        enrollment.created = self.course.start
        enrollment.save()
        CourseDurationLimitConfig.objects.create(
            enabled=True,
            course=CourseOverview.get_from_id(self.course.id),
            enabled_as_of=self.course.start,
        )

        instructor = UserFactory.create(username='******')
        CourseEnrollmentFactory.create(
            user=instructor,
            course_id=self.course.id,
            mode='audit'
        )
        CourseInstructorRole(self.course.id).add_users(instructor)
        self.client.login(username=instructor.username, password='******')

        self.update_masquerade(username='******')

        course_home_url = reverse('openedx.course_experience.course_home', args=[six.text_type(self.course.id)])
        response = self.client.get(course_home_url, follow=True)
        self.assertEqual(response.status_code, 200)
        self.assertItemsEqual(response.redirect_chain, [])
        banner_text = 'This learner does not have access to this course. Their access expired on'
        self.assertIn(banner_text, response.content)
Example #7
0
    def _create_cert(self, course_key, user, status):
        """Create a certificate entry. """
        # Enroll the user in the course
        CourseEnrollmentFactory.create(user=user, course_id=course_key)

        # Create the certificate
        GeneratedCertificate.objects.create(user=user, course_id=course_key, status=status)
    def setUp(self):
        super(TestGradebook, self).setUp()

        instructor = AdminFactory.create()
        self.client.login(username=instructor.username, password='******')
        self.users = [UserFactory.create() for _ in xrange(USER_COUNT)]

        for user in self.users:
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

        for i, item in enumerate(self.items):
            for j, user in enumerate(self.users):
                StudentModuleFactory.create(
                    grade=1 if i < j else 0,
                    max_grade=1,
                    student=user,
                    course_id=self.course.id,
                    module_state_key=item.location
                )

        self.response = self.client.get(reverse(
            'spoc_gradebook',
            args=(self.course.id.to_deprecated_string(),)
        ))

        self.assertEquals(self.response.status_code, 200)
Example #9
0
 def setUp(self):
     super(CCXCoachTabTestCase, self).setUp()
     self.user = UserFactory.create()
     for course in [self.ccx_enabled_course, self.ccx_disabled_course]:
         CourseEnrollmentFactory.create(user=self.user, course_id=course.id)
         role = CourseCcxCoachRole(course.id)
         role.add_users(self.user)
    def setUp(self):
        """
        Setup course structure and create user for split test transformer test.
        """
        super(SplitTestTransformerTestCase, self).setUp()

        # Set up user partitions and groups.
        self.groups = [Group(1, 'Group 1'), Group(2, 'Group 2'), Group(3, 'Group 3')]
        self.split_test_user_partition_id = self.TEST_PARTITION_ID
        self.split_test_user_partition = UserPartition(
            id=self.split_test_user_partition_id,
            name='Split Partition',
            description='This is split partition',
            groups=self.groups,
            scheme=RandomUserPartitionScheme
        )
        self.split_test_user_partition.scheme.name = "random"

        # Build course.
        self.course_hierarchy = self.get_course_hierarchy()
        self.blocks = self.build_course(self.course_hierarchy)
        self.course = self.blocks['course']

        # Enroll user in course.
        CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, is_active=True)

        self.transformer = UserPartitionTransformer()
    def setUp(self):
        super(TestGetProblemGradeDistribution, self).setUp()

        self.request_factory = RequestFactory()
        self.instructor = AdminFactory.create()
        self.client.login(username=self.instructor.username, password='******')
        self.attempts = 3
        self.course = CourseFactory.create(
            display_name=u"test course omega \u03a9",
        )

        section = ItemFactory.create(
            parent_location=self.course.location,
            category="chapter",
            display_name=u"test factory section omega \u03a9",
        )
        self.sub_section = ItemFactory.create(
            parent_location=section.location,
            category="sequential",
            display_name=u"test subsection omega \u03a9",
        )

        unit = ItemFactory.create(
            parent_location=self.sub_section.location,
            category="vertical",
            metadata={'graded': True, 'format': 'Homework'},
            display_name=u"test unit omega \u03a9",
        )

        self.users = [UserFactory.create(username="******" + str(__)) for __ in xrange(USER_COUNT)]

        for user in self.users:
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

        for i in xrange(USER_COUNT - 1):
            category = "problem"
            self.item = ItemFactory.create(
                parent_location=unit.location,
                category=category,
                data=StringResponseXMLFactory().build_xml(answer='foo'),
                metadata={'rerandomize': 'always'},
                display_name=u"test problem omega \u03a9 " + str(i)
            )

            for j, user in enumerate(self.users):
                StudentModuleFactory.create(
                    grade=1 if i < j else 0,
                    max_grade=1 if i < j else 0.5,
                    student=user,
                    course_id=self.course.id,
                    module_state_key=self.item.location,
                    state=json.dumps({'attempts': self.attempts}),
                )

            for j, user in enumerate(self.users):
                StudentModuleFactory.create(
                    course_id=self.course.id,
                    module_type='sequential',
                    module_state_key=self.item.location,
                )
    def setUp(self):
        super(CertificatesViewsTests, self).setUp()
        self.client = Client()
        self.course = CourseFactory.create(
            org='testorg', number='run1', display_name='refundable course'
        )
        self.course_id = self.course.location.course_key
        self.user = UserFactory.create(
            email='*****@*****.**',
            username='******',
            password='******'
        )
        self.user.profile.name = "Joe User"
        self.user.profile.save()
        self.client.login(username=self.user.username, password='******')
        self.request = RequestFactory().request()

        self.cert = GeneratedCertificateFactory.create(
            user=self.user,
            course_id=self.course_id,
            download_uuid=uuid4(),
            download_url="http://www.example.com/certificates/download",
            grade="0.95",
            key='the_key',
            distinction=True,
            status='downloadable',
            mode='honor',
            name=self.user.profile.name,
        )
        CourseEnrollmentFactory.create(
            user=self.user,
            course_id=self.course_id
        )
        CertificateHtmlViewConfigurationFactory.create()
        LinkedInAddToProfileConfigurationFactory.create()
Example #13
0
    def setup_course(self):
        self.course = CourseFactory.create(data=self.COURSE_DATA)

        # Turn off cache.
        modulestore().request_cache = None
        modulestore().metadata_inheritance_cache_subsystem = None

        chapter = ItemFactory.create(
            parent_location=self.course.location,
            category="sequential",
        )
        self.section = ItemFactory.create(
            parent_location=chapter.location,
            category="sequential"
        )

        # username = robot{0}, password = '******'
        self.users = [
            UserFactory.create()
            for i in range(self.USER_COUNT)
        ]

        for user in self.users:
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

        # login all users for acces to Xmodule
        self.clients = {user.username: Client() for user in self.users}
        self.login_statuses = [
            self.clients[user.username].login(
                username=user.username, password='******')
            for user in self.users
        ]

        self.assertTrue(all(self.login_statuses))
Example #14
0
    def setUp(self):
        super(TestBlockListGetForm, self).setUp()

        self.student = UserFactory.create()
        self.student2 = UserFactory.create()
        self.staff = UserFactory.create(is_staff=True)

        CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
        CourseEnrollmentFactory.create(user=self.student2, course_id=self.course.id)

        usage_key = self.course.location
        self.initial = {"requesting_user": self.student}
        self.form_data = QueryDict(
            urlencode({"username": self.student.username, "usage_key": unicode(usage_key)}), mutable=True
        )
        self.cleaned_data = {
            "all_blocks": None,
            "block_counts": set(),
            "depth": 0,
            "nav_depth": None,
            "return_type": "dict",
            "requested_fields": {"display_name", "type"},
            "student_view_data": set(),
            "usage_key": usage_key,
            "username": self.student.username,
            "user": self.student,
        }
Example #15
0
 def _create_user(self, username, email=None, is_staff=False, mode="honor"):
     """Creates a user and enrolls them in the test course."""
     if email is None:
         email = InstructorTaskCourseTestCase.get_user_email(username)
     thisuser = UserFactory.create(username=username, email=email, is_staff=is_staff)
     CourseEnrollmentFactory.create(user=thisuser, course_id=self.course.id, mode=mode)
     return thisuser
    def setUp(self):
        self.course_name = 'edX/toy/2012_Fall'

        # Create student account
        student = UserFactory.create()
        CourseEnrollmentFactory.create(
            user=student,
            course_id=SlashSeparatedCourseKey.from_deprecated_string(self.course_name)
        )
        self.client.login(username=student.username, password="******")

        try:
            # URL for dashboard
            self.url = reverse('dashboard')
        except NoReverseMatch:
            raise SkipTest("Skip this test if url cannot be found (ie running from CMS tests)")

        # URL for email settings modal
        self.email_modal_link = (
            ('<a href="#email-settings-modal" class="email-settings" rel="leanModal" '
             'data-course-id="{0}/{1}/{2}" data-course-number="{1}" '
             'data-optout="False">Email Settings</a>').format(
                 'edX',
                 'toy',
                 '2012_Fall'
             )
        )
Example #17
0
 def create_course(self, modules_count, module_store, topics):
     """
     Create a course in a specified module store with discussion module and topics
     """
     course = CourseFactory.create(
         org="a",
         course="b",
         run="c",
         start=datetime.now(UTC),
         default_store=module_store,
         discussion_topics=topics
     )
     CourseEnrollmentFactory.create(user=self.user, course_id=course.id)
     course_url = reverse("course_topics", kwargs={"course_id": unicode(course.id)})
     # add some discussion modules
     for i in range(modules_count):
         ItemFactory.create(
             parent_location=course.location,
             category='discussion',
             discussion_id='id_module_{}'.format(i),
             discussion_category='Category {}'.format(i),
             discussion_target='Discussion {}'.format(i),
             publish_item=False,
         )
     return course_url
    def test_data_err_fail(self, retry, result):
        """
        Test that celery handles permanent SMTPDataErrors by failing and not retrying.
        """
        self.smtp_server_thread.server.set_errtype(
            "DATA",
            "554 Message rejected: Email address is not verified."
        )

        students = [UserFactory() for _ in xrange(settings.EMAILS_PER_TASK)]
        for student in students:
            CourseEnrollmentFactory.create(user=student, course_id=self.course.id)

        test_email = {
            'action': 'Send email',
            'to_option': 'all',
            'subject': 'test subject for all',
            'message': 'test message for all'
        }
        self.client.post(self.url, test_email)

        # We shouldn't retry when hitting a 5xx error
        self.assertFalse(retry.called)
        # Test that after the rejected email, the rest still successfully send
        ((sent, fail, optouts), _) = result.call_args
        self.assertEquals(optouts, 0)
        self.assertEquals(fail, 1)
        self.assertEquals(sent, settings.EMAILS_PER_TASK - 1)
Example #19
0
    def test_access_masquerade_as_user_with_forum_role(self, role_name):
        """
        Test that when masquerading as a user with a given forum role you do not lose access to graded content
        """
        staff_user = StaffFactory.create(password=TEST_PASSWORD, course_key=self.course.id)
        CourseEnrollmentFactory.create(
            user=staff_user,
            course_id=self.course.id,
            mode='audit'
        )
        self.client.login(username=staff_user.username, password=TEST_PASSWORD)

        user = UserFactory.create()
        role = RoleFactory(name=role_name, course_id=self.course.id)
        role.users.add(user)

        CourseEnrollmentFactory.create(
            user=user,
            course_id=self.course.id,
            mode='audit'
        )

        self.update_masquerade(username=user.username)

        _assert_block_is_gated(
            block=self.blocks_dict['problem'],
            user=user,
            course=self.course,
            is_gated=False,
            request_factory=self.factory,
        )
Example #20
0
 def test_double_denied(self):
     ''' First graded problem should show message, second shouldn't '''
     course = self._create_course()
     blocks_dict = course['blocks']
     blocks_dict['graded_1'] = ItemFactory.create(
         parent=blocks_dict['vertical'],
         category='problem',
         graded=True,
         metadata=METADATA,
     )
     blocks_dict['graded_2'] = ItemFactory.create(
         parent=blocks_dict['vertical'],
         category='problem',
         graded=True,
         metadata=METADATA,
     )
     CourseEnrollmentFactory.create(
         user=self.user,
         course_id=course['course'].id,
         mode='audit'
     )
     _assert_block_is_gated(
         block=blocks_dict['graded_1'],
         user=self.user,
         course=course['course'],
         is_gated=True,
         request_factory=self.request_factory,
     )
     _assert_block_is_empty(
         block=blocks_dict['graded_2'],
         user_id=self.user.id,
         course=course['course'],
         request_factory=self.request_factory,
     )
Example #21
0
    def test_access_masquerade_as_course_team_users(self, role_factory):
        """
        Test that when masquerading as members of the course team you do not lose access to graded content
        """
        # There are two types of course team members: instructor and staff
        # they have different privileges, but for the purpose of this test the important thing is that they should both
        # have access to all graded content
        staff_user = StaffFactory.create(password=TEST_PASSWORD, course_key=self.course.id)
        CourseEnrollmentFactory.create(
            user=staff_user,
            course_id=self.course.id,
            mode='audit'
        )
        self.client.login(username=staff_user.username, password=TEST_PASSWORD)

        if role_factory == GlobalStaffFactory:
            user = role_factory.create()
        else:
            user = role_factory.create(course_key=self.course.id)
        self.update_masquerade(username=user.username)

        block = self.blocks_dict['problem']
        block_view_url = reverse('render_xblock', kwargs={'usage_key_string': six.text_type(block.scope_ids.usage_id)})
        response = self.client.get(block_view_url)
        self.assertEquals(response.status_code, 200)
Example #22
0
    def test_access_course_team_users(self, role_factory):
        """
        Test that members of the course team do not lose access to graded content
        """
        # There are two types of course team members: instructor and staff
        # they have different privileges, but for the purpose of this test the important thing is that they should both
        # have access to all graded content
        if role_factory == GlobalStaffFactory:
            user = role_factory.create()
        else:
            user = role_factory.create(course_key=self.course.id)

        CourseEnrollmentFactory.create(
            user=user,
            course_id=self.course.id,
            mode='audit',
        )

        # assert that course team members have access to graded content
        _assert_block_is_gated(
            block=self.blocks_dict['problem'],
            user=user,
            course=self.course,
            is_gated=False,
            request_factory=self.factory,
        )
Example #23
0
    def setUp(self):
        """
        Create the test data.
        """
        super(CompletionBatchTestCase, self).setUp()
        self.url = reverse('completion_api:v1:completion-batch')

        # Enable the waffle flag for all tests
        self.override_waffle_switch(True)

        # Create course
        self.course = CourseFactory.create(org='TestX', number='101', display_name='Test')
        self.problem = ItemFactory.create(
            parent=self.course,
            category="problem",
            display_name="Test Problem",
        )

        # Create users
        self.staff_user = UserFactory(is_staff=True)
        self.enrolled_user = UserFactory(username=self.ENROLLED_USERNAME)
        self.unenrolled_user = UserFactory(username=self.UNENROLLED_USERNAME)

        # Enrol one user in the course
        CourseEnrollmentFactory.create(user=self.enrolled_user, course_id=self.course.id)

        # Login the enrolled user by for all tests
        self.client = APIClient()
        self.client.force_authenticate(user=self.enrolled_user)
Example #24
0
    def test_unicode_students_send_to_all(self):
        """
        Make sure email (with Unicode characters) send to all goes there.
        """
        # Now we know we have pulled up the instructor dash's email view
        # (in the setUp method), we can test sending an email.

        # Create a student with Unicode in their first & last names
        unicode_user = UserFactory(first_name=u'ā“‡ā“žā“‘ā“žā“£', last_name=u'Շļ»‰ąø£Õ‡')
        CourseEnrollmentFactory.create(user=unicode_user, course_id=self.course.id)
        self.students.append(unicode_user)

        test_email = {
            'action': 'Send email',
            'send_to': 'all',
            'subject': 'test subject for all',
            'message': 'test message for all'
        }
        # Post the email to the instructor dashboard API
        response = self.client.post(self.send_mail_url, test_email)
        self.assertEquals(json.loads(response.content), self.success_content)

        self.assertEquals(len(mail.outbox), 1 + len(self.staff) + len(self.students))

        self.assertItemsEqual(
            [e.to[0] for e in mail.outbox],
            [self.instructor.email] + [s.email for s in self.staff] + [s.email for s in self.students]
        )
    def setUp(self):
        super(TestGetProblemGradeDistribution, self).setUp()

        self.request_factory = RequestFactory()
        self.instructor = AdminFactory.create()
        self.client.login(username=self.instructor.username, password='******')
        self.attempts = 3
        self.users = [
            UserFactory.create(username="******" + str(__))
            for __ in xrange(USER_COUNT)
        ]

        for user in self.users:
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

        for i, item in enumerate(self.items):
            for j, user in enumerate(self.users):
                StudentModuleFactory.create(
                    grade=1 if i < j else 0,
                    max_grade=1 if i < j else 0.5,
                    student=user,
                    course_id=self.course.id,
                    module_state_key=item.location,
                    state=json.dumps({'attempts': self.attempts}),
                )
            for j, user in enumerate(self.users):
                StudentModuleFactory.create(
                    course_id=self.course.id,
                    module_type='sequential',
                    module_state_key=item.location,
                )
Example #26
0
    def setUp(self):
        course_title = u"įŗ—Ć«į¹”įŗ— title ļ½²ä¹‡äø‚ļ½² ļ¾¶ä¹‡äø‚äø‚ļ¾‘g乇 ļ½·oå°ŗ ļ¾‘ļ¾šļ¾š тэѕт Š¼ŃŃ•Ń•Š°Š‘э"
        self.course = CourseFactory.create(display_name=course_title)

        self.instructor = InstructorFactory(course=self.course.id)

        # Create staff
        self.staff = [StaffFactory(course=self.course.id)
                      for _ in xrange(STAFF_COUNT)]

        # Create students
        self.students = [UserFactory() for _ in xrange(STUDENT_COUNT)]
        for student in self.students:
            CourseEnrollmentFactory.create(user=student, course_id=self.course.id)

        # load initial content (since we don't run migrations as part of tests):
        call_command("loaddata", "course_email_template.json")

        self.client.login(username=self.instructor.username, password="******")

        # Pull up email view on instructor dashboard
        self.url = reverse('instructor_dashboard', kwargs={'course_id': self.course.id.to_deprecated_string()})
        # Response loads the whole instructor dashboard, so no need to explicitly
        # navigate to a particular email section
        response = self.client.get(self.url)
        email_section = '<div class="vert-left send-email" id="section-send-email">'
        # If this fails, it is likely because ENABLE_INSTRUCTOR_EMAIL is set to False
        self.assertTrue(email_section in response.content)
        self.send_mail_url = reverse('send_email', kwargs={'course_id': self.course.id.to_deprecated_string()})
        self.success_content = {
            'course_id': self.course.id.to_deprecated_string(),
            'success': True,
        }
Example #27
0
 def setUp(self):
     super(DiscussionTabTestCase, self).setUp()
     self.course = CourseFactory.create()
     self.enrolled_user = UserFactory.create()
     self.staff_user = AdminFactory.create()
     CourseEnrollmentFactory.create(user=self.enrolled_user, course_id=self.course.id)
     self.unenrolled_user = UserFactory.create()
Example #28
0
    def setUp(self):
        self.partition = UserPartition(
            0,
            'first_partition',
            'First Partition',
            [
                Group(0, 'alpha'),
                Group(1, 'beta')
            ]
        )

        self.course = CourseFactory.create(
            number=self.COURSE_NUMBER,
            user_partitions=[self.partition]
        )

        self.chapter = ItemFactory.create(
            parent_location=self.course.location,
            category="chapter",
            display_name="test chapter",
        )
        self.sequential = ItemFactory.create(
            parent_location=self.chapter.location,
            category="sequential",
            display_name="Split Test Tests",
        )

        self.student = UserFactory.create()
        CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
        self.client.login(username=self.student.username, password='******')
Example #29
0
    def test_unicode_students_send_to_all(self):
        """
        Make sure email (with Unicode characters) send to all goes there.
        """

        # Create a student with Unicode in their first & last names
        unicode_user = UserFactory(first_name=u'ā“‡ā“žā“‘ā“žā“£', last_name=u'Շļ»‰ąø£Õ‡')
        CourseEnrollmentFactory.create(user=unicode_user, course_id=self.course.id)
        self.students.append(unicode_user)

        test_email = {
            'action': 'Send email',
            'send_to': '["myself", "staff", "learners"]',
            'subject': 'test subject for all',
            'message': 'test message for all'
        }
        response = self.client.post(self.send_mail_url, test_email)
        self.assertEquals(json.loads(response.content), self.success_content)

        self.assertEquals(len(mail.outbox), 1 + len(self.staff) + len(self.students))

        self.assertItemsEqual(
            [e.to[0] for e in mail.outbox],
            [self.instructor.email] + [s.email for s in self.staff] + [s.email for s in self.students]
        )
Example #30
0
    def test_data_err_fail(self, retry, result, get_conn):
        """
        Test that celery handles permanent SMTPDataErrors by failing and not retrying.
        """
        # have every fourth email fail due to blacklisting:
        get_conn.return_value.send_messages.side_effect = cycle([SMTPDataError(554, "Email address is blacklisted"),
                                                                 None, None, None])
        students = [UserFactory() for _ in xrange(settings.BULK_EMAIL_EMAILS_PER_TASK)]
        for student in students:
            CourseEnrollmentFactory.create(user=student, course_id=self.course.id)

        test_email = {
            'action': 'Send email',
            'send_to': 'all',
            'subject': 'test subject for all',
            'message': 'test message for all'
        }
        response = self.client.post(self.send_mail_url, test_email)
        self.assertEquals(json.loads(response.content), self.success_content)

        # We shouldn't retry when hitting a 5xx error
        self.assertFalse(retry.called)
        # Test that after the rejected email, the rest still successfully send
        ((_entry_id, _current_task_id, subtask_status), _kwargs) = result.call_args
        self.assertEquals(subtask_status.skipped, 0)
        expected_fails = int((settings.BULK_EMAIL_EMAILS_PER_TASK + 3) / 4.0)
        self.assertEquals(subtask_status.failed, expected_fails)
        self.assertEquals(subtask_status.succeeded, settings.BULK_EMAIL_EMAILS_PER_TASK - expected_fails)
Example #31
0
    def test_student_has_access(self):
        """
        Tests course student have right access to content w/o preview.
        """
        course_key = self.course.id
        chapter = ItemFactory.create(category="chapter",
                                     parent_location=self.course.location)
        overview = CourseOverview.get_from_id(course_key)

        # Enroll student to the course
        CourseEnrollmentFactory(user=self.student, course_id=self.course.id)

        modules = [
            self.course,
            overview,
            chapter,
        ]
        with patch('courseware.access.in_preview_mode') as mock_preview:
            mock_preview.return_value = False
            for obj in modules:
                self.assertTrue(
                    bool(
                        access.has_access(self.student,
                                          'load',
                                          obj,
                                          course_key=self.course.id)))

        with patch('courseware.access.in_preview_mode') as mock_preview:
            mock_preview.return_value = True
            for obj in modules:
                self.assertFalse(
                    bool(
                        access.has_access(self.student,
                                          'load',
                                          obj,
                                          course_key=self.course.id)))
Example #32
0
    def test_access_on_course_with_pre_requisites(self):
        """
        Test course access when a course has pre-requisite course yet to be completed
        """
        seed_milestone_relationship_types()
        user = UserFactory.create()

        pre_requisite_course = CourseFactory.create(org='test_org',
                                                    number='788',
                                                    run='test_run')

        pre_requisite_courses = [unicode(pre_requisite_course.id)]
        course = CourseFactory.create(
            org='test_org',
            number='786',
            run='test_run',
            pre_requisite_courses=pre_requisite_courses)
        set_prerequisite_courses(course.id, pre_requisite_courses)

        # user should not be able to load course even if enrolled
        CourseEnrollmentFactory(user=user, course_id=course.id)
        response = access._has_access_course_desc(
            user, 'view_courseware_with_prerequisites', course)
        self.assertFalse(response)
        self.assertIsInstance(response, access_response.MilestoneError)
        # Staff can always access course
        staff = StaffFactory.create(course_key=course.id)
        self.assertTrue(
            access._has_access_course_desc(
                staff, 'view_courseware_with_prerequisites', course))

        # User should be able access after completing required course
        fulfill_course_milestone(pre_requisite_course.id, user)
        self.assertTrue(
            access._has_access_course_desc(
                user, 'view_courseware_with_prerequisites', course))
Example #33
0
    def test_professional_enrollment(self, mode):
        # The only course mode is professional ed
        CourseModeFactory(mode_slug=mode, course_id=self.course.id, min_price=1)

        # Go to the "choose your track" page
        choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
        response = self.client.get(choose_track_url)

        # Since the only available track is professional ed, expect that
        # we're redirected immediately to the start of the payment flow.
        start_flow_url = reverse('verify_student_start_flow', args=[unicode(self.course.id)])
        self.assertRedirects(response, start_flow_url)

        # Now enroll in the course
        CourseEnrollmentFactory(
            user=self.user,
            is_active=True,
            mode=mode,
            course_id=unicode(self.course.id),
        )

        # Expect that this time we're redirected to the dashboard (since we're already registered)
        response = self.client.get(choose_track_url)
        self.assertRedirects(response, reverse('dashboard'))
Example #34
0
    def test_get_visible_sessions_for_entitlement_expired_mode(self, mock_get_edx_api_data):
        """
        Test retrieval of visible session entitlements.
        """
        catalog_course_run = CourseRunFactory.create()
        catalog_course = CourseFactory(course_runs=[catalog_course_run])
        mock_get_edx_api_data.return_value = catalog_course
        course_key = CourseKey.from_string(catalog_course_run.get('key'))
        course_overview = CourseOverviewFactory.create(id=course_key, start=self.tomorrow)
        CourseModeFactory.create(
            mode_slug=CourseMode.VERIFIED,
            min_price=100,
            course_id=course_overview.id,
            expiration_datetime=now() - timedelta(days=1)
        )
        course_enrollment = CourseEnrollmentFactory(
            user=self.user, course_id=unicode(course_overview.id), mode=CourseMode.VERIFIED
        )
        entitlement = CourseEntitlementFactory(
            user=self.user, enrollment_course_run=course_enrollment, mode=CourseMode.VERIFIED
        )

        session_entitlements = get_visible_sessions_for_entitlement(entitlement)
        self.assertEqual(session_entitlements, [catalog_course_run])
Example #35
0
    def test_username_exact_match(self):
        """
        Ensure that course enrollment searches return exact matches on username first.
        """
        user2 = UserFactory.create(
            username='******'.format(self.user.username))
        CourseEnrollmentFactory(
            user=user2,
            course_id=self.course.id,  # pylint: disable=no-member
        )
        search_url = '{}?q={}'.format(
            reverse('admin:student_courseenrollment_changelist'),
            self.user.username)
        with COURSE_ENROLLMENT_ADMIN_SWITCH.override(active=True):
            response = self.client.get(search_url)
        self.assertEqual(response.status_code, 200)

        # context['results'] is an array of arrays of HTML <td> elements to be rendered
        self.assertEqual(len(response.context['results']), 2)
        for idx, username in enumerate([self.user.username, user2.username]):
            # Locate the <td> column containing the username
            user_field = next(col for col in response.context['results'][idx]
                              if "field-user" in col)
            self.assertIn(username, user_field)
Example #36
0
    def test_learner_already_enrolled_in_course(self):
        course_key = self.course_keys[0]
        course = CourseOverview.objects.get(id=course_key)
        CourseEnrollmentFactory(user=self.user,
                                course=course,
                                mode=CourseMode.VERIFIED)

        program_enrollment = self._create_waiting_program_enrollment()
        program_course_enrollments = self._create_waiting_course_enrollments(
            program_enrollment)

        UserSocialAuth.objects.create(user=self.user,
                                      uid='{0}:{1}'.format(
                                          self.provider_slug,
                                          self.external_id))

        self._assert_program_enrollment_user(program_enrollment, self.user)

        duplicate_program_course_enrollment = program_course_enrollments[0]
        self._assert_program_course_enrollment(
            duplicate_program_course_enrollment, CourseMode.VERIFIED)

        program_course_enrollment = program_course_enrollments[1]
        self._assert_program_course_enrollment(program_course_enrollment)
Example #37
0
    def test_suggested_prices(self, price_list):

        # Create the course modes
        for mode in ('audit', 'honor'):
            CourseModeFactory.create(mode_slug=mode, course_id=self.course.id)

        CourseModeFactory.create(mode_slug='verified',
                                 course_id=self.course.id,
                                 suggested_prices=price_list)

        # Enroll the user in the test course to emulate
        # automatic enrollment
        CourseEnrollmentFactory(is_active=True,
                                course_id=self.course.id,
                                user=self.user)

        # Verify that the prices render correctly
        response = self.client.get(
            reverse('course_modes_choose',
                    args=[six.text_type(self.course.id)]),
            follow=False,
        )

        self.assertEquals(response.status_code, 200)
Example #38
0
    def test_student_enrollment_status(self, is_enrolled, enrolled_mode, is_upgrade_required, mock_get_mode):
        """Verify that program data is supplemented with the student's enrollment status."""
        expected_upgrade_url = '{root}/{path}?sku={sku}'.format(
            root=ECOMMERCE_URL_ROOT,
            path=self.checkout_path.strip('/'),
            sku=self.sku,
        )

        update_commerce_config(enabled=True, checkout_page=self.checkout_path)

        mock_mode = mock.Mock()
        mock_mode.sku = self.sku
        mock_get_mode.return_value = mock_mode

        if is_enrolled:
            CourseEnrollmentFactory(user=self.user, course_id=self.course.id, mode=enrolled_mode)

        data = ProgramDataExtender(self.program, self.user).extend()

        self._assert_supplemented(
            data,
            is_enrolled=is_enrolled,
            upgrade_url=expected_upgrade_url if is_upgrade_required else None
        )
    def test_with_course_data(self, mock_get_current_site):
        self.highlights_patcher.stop()
        mock_get_current_site.return_value = self.site_config.site

        course = CourseFactory(highlights_enabled_for_messaging=True, self_paced=True)
        with self.store.bulk_operations(course.id):
            ItemFactory.create(parent=course, category='chapter', highlights=[u'highlights'])

        enrollment = CourseEnrollmentFactory(course_id=course.id, user=self.user, mode=u'audit')
        self.assertEqual(enrollment.schedule.get_experience_type(), ScheduleExperience.EXPERIENCES.course_updates)

        _, offset, target_day, _ = self._get_dates(offset=self.expected_offsets[0])
        enrollment.schedule.start = target_day
        enrollment.schedule.save()

        with patch.object(tasks, 'ace') as mock_ace:
            self.task().apply(kwargs=dict(  # pylint: disable=no-value-for-parameter
                site_id=self.site_config.site.id,
                target_day_str=serialize(target_day),
                day_offset=offset,
                bin_num=self._calculate_bin_for_user(enrollment.user),
            ))

            self.assertTrue(mock_ace.send.called)
    def _create_courses_and_enrollments(self, *args):
        """Create courses and enrollments.

        Created courses and enrollments are stored in instance variables
        so tests can refer to them later.

        Arguments:
            *args: Tuples of (course_org, should_enroll), where
                course_org is the name of the org in the course key
                and should_enroll is a boolean indicating whether to enroll
                the user in the course.

        Returns:
            None

        """
        for course_number, (course_org, should_enroll) in enumerate(args):
            course = CourseFactory.create(org=course_org,
                                          number=str(course_number))
            if should_enroll:
                enrollment = CourseEnrollmentFactory.create(
                    is_active=True, course_id=course.id, user=self.user)
                self.enrollments[course.id].append(enrollment)
            self.courses.append(course)
Example #41
0
    def test_content_gating_course_card_changes(self):
        """
        When a course is expired, the links on the course card should be removed.
        Links will be removed from the course title, course image and button (View Course/Resume Course).
        The course card should have an access expired message.
        """
        CourseDurationLimitConfig.objects.create(enabled=True, enabled_as_of=self.THREE_YEARS_AGO - timedelta(days=30))
        self.override_waffle_switch(True)

        course = CourseFactory.create(start=self.THREE_YEARS_AGO)
        add_course_mode(course, mode_slug=CourseMode.AUDIT)
        add_course_mode(course)
        enrollment = CourseEnrollmentFactory.create(
            user=self.user,
            course_id=course.id
        )
        enrollment.created = self.THREE_YEARS_AGO + timedelta(days=1)
        enrollment.save()

        # pylint: disable=unused-variable
        schedule = ScheduleFactory(enrollment=enrollment)

        response = self.client.get(reverse('dashboard'))
        dashboard_html = self._remove_whitespace_from_response(response)
        access_expired_substring = 'Accessexpired'
        course_link_class = 'course-target-link'

        self.assertNotIn(
            course_link_class,
            dashboard_html
        )

        self.assertIn(
            access_expired_substring,
            dashboard_html
        )
Example #42
0
    def test_masquerade(self, masquerade_config, show_expiration_banner, mock_get_course_run_details):
        mock_get_course_run_details.return_value = {'weeks_to_complete': 12}
        audit_student = UserFactory(username='******')
        CourseEnrollmentFactory.create(
            user=audit_student,
            course_id=self.course.id,
            mode='audit'
        )
        verified_student = UserFactory(username='******')
        CourseEnrollmentFactory.create(
            user=verified_student,
            course_id=self.course.id,
            mode='verified'
        )
        CourseDurationLimitConfig.objects.create(
            enabled=True,
            course=CourseOverview.get_from_id(self.course.id),
            enabled_as_of=self.course.start,
        )

        instructor = UserFactory.create(username='******')
        CourseEnrollmentFactory.create(
            user=instructor,
            course_id=self.course.id,
            mode='audit'
        )
        CourseInstructorRole(self.course.id).add_users(instructor)
        self.client.login(username=instructor.username, password='******')

        self.update_masquerade(**masquerade_config)

        course_home_url = reverse('openedx.course_experience.course_home', args=[six.text_type(self.course.id)])
        response = self.client.get(course_home_url, follow=True)
        self.assertEqual(response.status_code, 200)
        six.assertCountEqual(self, response.redirect_chain, [])
        banner_text = 'You lose all access to this course, including your progress,'
        if show_expiration_banner:
            self.assertContains(response, banner_text)
        else:
            self.assertNotContains(response, banner_text)
Example #43
0
 def setUp(self):
     super(TestModels, self).setUp()
     self.course = CourseOverviewFactory.create(start=datetime.utcnow())
     self.enrollment = CourseEnrollmentFactory.create(
         course_id=self.course.id)
    def test_spoc_gradebook_mongo_calls(self):
        """
        Test that the MongoDB cache is used in API to return grades
        """
        # prepare course structure
        course = ItemFactory.create(
            parent_location=self.course.location,
            category="course",
            display_name="Test course",
        )

        students = []
        for i in range(20):
            username = "******" % i
            student = UserFactory.create(username=username)
            CourseEnrollmentFactory.create(user=student, course_id=self.course.id)
            students.append(student)

        chapter = ItemFactory.create(
            parent=course,
            category='chapter',
            display_name="Chapter",
            publish_item=True,
            start=datetime.datetime(2015, 3, 1, tzinfo=UTC),
        )
        sequential = ItemFactory.create(
            parent=chapter,
            category='sequential',
            display_name="Lesson",
            publish_item=True,
            start=datetime.datetime(2015, 3, 1, tzinfo=UTC),
            metadata={'graded': True, 'format': 'Homework'},
        )
        vertical = ItemFactory.create(
            parent=sequential,
            category='vertical',
            display_name='Subsection',
            publish_item=True,
            start=datetime.datetime(2015, 4, 1, tzinfo=UTC),
        )
        for i in range(10):
            problem = ItemFactory.create(
                category="problem",
                parent=vertical,
                display_name=u"A Problem Block %d" % i,
                weight=1,
                publish_item=False,
                metadata={'rerandomize': 'always'},
            )
            for j in students:
                grade = i % 2
                StudentModuleFactory.create(
                    grade=grade,
                    max_grade=1,
                    student=j,
                    course_id=self.course.id,
                    module_state_key=problem.location
                )

        # check MongoDB calls count
        url = reverse('spoc_gradebook', kwargs={'course_id': self.course.id})
        with check_mongo_calls(9):
            response = self.client.get(url)
            self.assertEqual(response.status_code, 200)
class VerifiedUpgradeToolTest(SharedModuleStoreTestCase):
    @classmethod
    def setUpClass(cls):
        super(VerifiedUpgradeToolTest, cls).setUpClass()
        cls.now = datetime.datetime.now(pytz.UTC)

        cls.course = CourseFactory.create(
            org='edX',
            number='test',
            display_name='Test Course',
            self_paced=True,
            start=cls.now - datetime.timedelta(days=30),
        )
        cls.course_overview = CourseOverview.get_from_id(cls.course.id)

    @override_waffle_flag(CREATE_SCHEDULE_WAFFLE_FLAG, True)
    def setUp(self):
        super(VerifiedUpgradeToolTest, self).setUp()

        self.course_verified_mode = CourseModeFactory(
            course_id=self.course.id,
            mode_slug=CourseMode.VERIFIED,
            expiration_datetime=self.now + datetime.timedelta(days=30),
        )

        patcher = patch(
            'openedx.core.djangoapps.schedules.signals.get_current_site')
        mock_get_current_site = patcher.start()
        self.addCleanup(patcher.stop)
        mock_get_current_site.return_value = SiteFactory.create()

        DynamicUpgradeDeadlineConfiguration.objects.create(enabled=True)

        self.request = RequestFactory().request()
        crum.set_current_request(self.request)
        self.addCleanup(crum.set_current_request, None)
        self.enrollment = CourseEnrollmentFactory(
            course_id=self.course.id,
            mode=CourseMode.AUDIT,
            course=self.course_overview,
        )
        self.request.user = self.enrollment.user

    def test_tool_visible(self):
        self.assertTrue(VerifiedUpgradeTool().is_enabled(
            self.request, self.course.id))

    def test_not_visible_when_no_enrollment_exists(self):
        self.enrollment.delete()

        request = RequestFactory().request()
        request.user = UserFactory()
        self.assertFalse(VerifiedUpgradeTool().is_enabled(
            self.request, self.course.id))

    def test_not_visible_when_using_deadline_from_course_mode(self):
        DynamicUpgradeDeadlineConfiguration.objects.create(enabled=False)
        self.assertFalse(VerifiedUpgradeTool().is_enabled(
            self.request, self.course.id))

    def test_not_visible_when_enrollment_is_inactive(self):
        self.enrollment.is_active = False
        self.enrollment.save()
        self.assertFalse(VerifiedUpgradeTool().is_enabled(
            self.request, self.course.id))

    def test_not_visible_when_already_verified(self):
        self.enrollment.mode = CourseMode.VERIFIED
        self.enrollment.save()
        self.assertFalse(VerifiedUpgradeTool().is_enabled(
            self.request, self.course.id))

    def test_not_visible_when_no_verified_track(self):
        self.course_verified_mode.delete()
        self.assertFalse(VerifiedUpgradeTool().is_enabled(
            self.request, self.course.id))

    def test_not_visible_when_course_deadline_has_passed(self):
        self.course_verified_mode.expiration_datetime = self.now - datetime.timedelta(
            days=1)
        self.course_verified_mode.save()
        self.assertFalse(VerifiedUpgradeTool().is_enabled(
            self.request, self.course.id))

    def test_not_visible_when_course_mode_has_no_deadline(self):
        self.course_verified_mode.expiration_datetime = None
        self.course_verified_mode.save()
        self.assertFalse(VerifiedUpgradeTool().is_enabled(
            self.request, self.course.id))
Example #46
0
    def test_dashboard_with_resume_buttons_and_view_buttons(self):
        '''
        The Test creates a four-course-card dashboard. The user completes course
        blocks in the even-numbered course cards. The test checks that courses
        with completion data have course cards with "Resume Course" buttons;
        those without have "View Course" buttons.

        '''
        self.override_waffle_switch(True)

        isEven = lambda n: n % 2 == 0

        num_course_cards = 4

        html_for_view_buttons = []
        html_for_resume_buttons = []
        html_for_entitlement = []

        for i in range(num_course_cards):

            course = CourseFactory.create()
            course_enrollment = CourseEnrollmentFactory(
                user=self.user,
                course_id=course.id
            )

            course_key = course_enrollment.course_id
            course_key_string = str(course_key)

            if i == 1:
                CourseEntitlementFactory.create(user=self.user, enrollment_course_run=course_enrollment)

            else:
                last_completed_block_string = ''
                course_run_string = self._pull_course_run_from_course_key(
                    course_key_string)

            # Submit completed course blocks in even-numbered courses.
            if isEven(i):
                block_keys = [
                    ItemFactory.create(
                        category='video',
                        parent_location=course.location,
                        display_name='Video {0}'.format(six.text_type(number))
                    ).location
                    for number in range(5)
                ]
                last_completed_block_string = str(block_keys[-1])

                submit_completions_for_testing(self.user, block_keys)

            html_for_view_buttons.append(
                self._get_html_for_view_course_button(
                    course_key_string,
                    course_run_string
                )
            )
            html_for_resume_buttons.append(
                self._get_html_for_resume_course_button(
                    course_key_string,
                    last_completed_block_string,
                    course_run_string
                )
            )
            html_for_entitlement.append(
                self._get_html_for_entitlement_button(
                    course_key_string
                )
            )

        response = self.client.get(reverse('dashboard'))

        html_for_view_buttons = [
            self._remove_whitespace_from_html_string(button)
            for button in html_for_view_buttons
        ]
        html_for_resume_buttons = [
            self._remove_whitespace_from_html_string(button)
            for button in html_for_resume_buttons
        ]
        html_for_entitlement = [
            self._remove_whitespace_from_html_string(button)
            for button in html_for_entitlement
        ]

        dashboard_html = self._remove_whitespace_from_response(response)

        for i in range(num_course_cards):
            expected_button = None
            unexpected_button = None

            if i == 1:
                expected_button = html_for_entitlement[i]
                unexpected_button = html_for_view_buttons[i] + html_for_resume_buttons[i]

            elif isEven(i):
                expected_button = html_for_resume_buttons[i]
                unexpected_button = html_for_view_buttons[i] + html_for_entitlement[i]
            else:
                expected_button = html_for_view_buttons[i]
                unexpected_button = html_for_resume_buttons[i] + html_for_entitlement[i]

            self.assertIn(
                expected_button,
                dashboard_html
            )
            self.assertNotIn(
                unexpected_button,
                dashboard_html
            )
Example #47
0
    def test_sessions_for_entitlement_course_runs(self, mock_course_overview, mock_course_runs):
        """
        When a learner has a fulfilled entitlement for a course run in the past, there should be no availableSession
        data passed to the JS view. When a learner has a fulfilled entitlement for a course run enrollment ending in the
        future, there should not be an empty availableSession variable. When a learner has a fulfilled entitlement
        for a course that doesn't have an enrollment ending, there should not be an empty availableSession variable.

        NOTE: We commented out the assertions to move this to the catalog utils test suite.
        """
        # noAvailableSessions = "availableSessions: '[]'"

        # Test an enrollment end in the past
        mocked_course_overview = CourseOverviewFactory.create(
            start=self.TOMORROW, end=self.THREE_YEARS_FROM_NOW, self_paced=True, enrollment_end=self.THREE_YEARS_AGO
        )
        mock_course_overview.return_value = mocked_course_overview
        course_enrollment = CourseEnrollmentFactory(user=self.user, course_id=six.text_type(mocked_course_overview.id))
        mock_course_runs.return_value = [
            {
                'key': str(mocked_course_overview.id),
                'enrollment_end': str(mocked_course_overview.enrollment_end),
                'pacing_type': 'self_paced',
                'type': 'verified',
                'status': 'published'
            }
        ]
        CourseEntitlementFactory(user=self.user, enrollment_course_run=course_enrollment)
        # response = self.client.get(self.path)
        # self.assertIn(noAvailableSessions, response.content)

        # Test an enrollment end in the future sets an availableSession
        mocked_course_overview.enrollment_end = self.TOMORROW
        mocked_course_overview.save()

        mock_course_overview.return_value = mocked_course_overview
        mock_course_runs.return_value = [
            {
                'key': str(mocked_course_overview.id),
                'enrollment_end': str(mocked_course_overview.enrollment_end),
                'pacing_type': 'self_paced',
                'type': 'verified',
                'status': 'published'
            }
        ]
        # response = self.client.get(self.path)
        # self.assertNotIn(noAvailableSessions, response.content)

        # Test an enrollment end that doesn't exist sets an availableSession
        mocked_course_overview.enrollment_end = None
        mocked_course_overview.save()

        mock_course_overview.return_value = mocked_course_overview
        mock_course_runs.return_value = [
            {
                'key': str(mocked_course_overview.id),
                'enrollment_end': None,
                'pacing_type': 'self_paced',
                'type': 'verified',
                'status': 'published'
            }
        ]
Example #48
0
    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='******')
 def test_no_verified_enrollment(self):
     course = create_course_run(days_till_start=-1)
     user = create_user()
     CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.AUDIT)
     block = VerificationDeadlineDate(course, user)
     self.assertFalse(block.is_enabled)
 def _enroll_users(self, mode):
     """Enroll users in the given mode."""
     for user in self.users:
         CourseEnrollmentFactory(mode=mode,
                                 course_id=self.course.id,
                                 user=user)
Example #51
0
 def test_no_verification_deadline(self):
     course = create_course_run(days_till_start=-1, days_till_verification_deadline=None)
     user = self.create_user()
     CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.VERIFIED)
     block = VerificationDeadlineDate(course, user)
     self.assertFalse(block.is_enabled)
Example #52
0
 def setUp(self):
     super(ContactUsViewTests, self).setUp()
     self.user = UserFactory()
     self.client.login(username=self.user.username, password='******')
     self.user_enrollment = CourseEnrollmentFactory.create(user=self.user, )
Example #53
0
 def test_upgrade_deadline_for_non_upgradeable_enrollment(self, mode):
     """ The property should return None if an upgrade cannot be upgraded. """
     enrollment = CourseEnrollmentFactory(course_id=self.course.id,
                                          mode=mode)
     self.assertIsNone(enrollment.upgrade_deadline)
 def create_student(self, username, email):
     student = UserFactory.create(username=username, email=email)
     CourseEnrollmentFactory.create(user=student, course_id=self.course.id)
     return student
 def test_enabled_block_types(self, course_kwargs, user_kwargs, expected_blocks):
     course = create_course_run(**course_kwargs)
     user = create_user(**user_kwargs)
     CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.VERIFIED)
     self.assert_block_types(course, user, expected_blocks)
Example #56
0
    def setUp(self):
        super(ContentGroupTestCase, self).setUp()

        self.course = CourseFactory.create(
            org='org',
            number='number',
            run='run',
            # This test needs to use a course that has already started --
            # discussion topics only show up if the course has already started,
            # and the default start date for courses is Jan 1, 2030.
            start=datetime(2012, 2, 3, tzinfo=UTC),
            user_partitions=[
                UserPartition(
                    0,
                    'Content Group Configuration',
                    '',
                    [Group(1, 'Alpha'), Group(2, 'Beta')],
                    scheme_id='cohort')
            ],
            grading_policy={
                "GRADER": [{
                    "type": "Homework",
                    "min_count": 1,
                    "drop_count": 0,
                    "short_label": "HW",
                    "weight": 1.0
                }]
            },
            cohort_config={'cohorted': True},
            discussion_topics={})

        self.staff_user = UserFactory.create(is_staff=True)
        self.alpha_user = UserFactory.create()
        self.beta_user = UserFactory.create()
        self.non_cohorted_user = UserFactory.create()
        for user in [
                self.staff_user, self.alpha_user, self.beta_user,
                self.non_cohorted_user
        ]:
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

        alpha_cohort = CohortFactory(course_id=self.course.id,
                                     name='Cohort Alpha',
                                     users=[self.alpha_user])
        beta_cohort = CohortFactory(course_id=self.course.id,
                                    name='Cohort Beta',
                                    users=[self.beta_user])
        CourseUserGroupPartitionGroup.objects.create(
            course_user_group=alpha_cohort,
            partition_id=self.course.user_partitions[0].id,
            group_id=self.course.user_partitions[0].groups[0].id)
        CourseUserGroupPartitionGroup.objects.create(
            course_user_group=beta_cohort,
            partition_id=self.course.user_partitions[0].id,
            group_id=self.course.user_partitions[0].groups[1].id)
        self.alpha_module = ItemFactory.create(
            parent_location=self.course.location,
            category='discussion',
            discussion_id='alpha_group_discussion',
            discussion_target='Visible to Alpha',
            group_access={
                self.course.user_partitions[0].id:
                [self.course.user_partitions[0].groups[0].id]
            })
        self.beta_module = ItemFactory.create(
            parent_location=self.course.location,
            category='discussion',
            discussion_id='beta_group_discussion',
            discussion_target='Visible to Beta',
            group_access={
                self.course.user_partitions[0].id:
                [self.course.user_partitions[0].groups[1].id]
            })
        self.global_module = ItemFactory.create(
            parent_location=self.course.location,
            category='discussion',
            discussion_id='global_group_discussion',
            discussion_target='Visible to Everyone')
        self.course = self.store.get_item(self.course.location)
 def test_enabled_block_types_with_non_upgradeable_course_run(self):
     course = create_course_run(days_till_start=-10, days_till_verification_deadline=None)
     user = create_user()
     CourseMode.objects.get(course_id=course.id, mode_slug=CourseMode.VERIFIED).delete()
     CourseEnrollmentFactory(course_id=course.id, user=user, mode=CourseMode.AUDIT)
     self.assert_block_types(course, user, (TodaysDate, CourseEndDate))
Example #58
0
    def setUp(self):
        """
        Set up a course with graded problems within a split test.

        Course hierarchy is as follows (modeled after how split tests
        are created in studio):
        -> course
            -> chapter
                -> sequential (graded)
                    -> vertical
                        -> split_test
                            -> vertical (Group A)
                                -> problem
                            -> vertical (Group B)
                                -> problem
        """
        super(TestConditionalContent, self).setUp()

        # Create user partitions
        self.user_partition_group_a = 0
        self.user_partition_group_b = 1
        self.partition = UserPartition(
            0, 'first_partition', 'First Partition', [
                Group(self.user_partition_group_a, 'Group A'),
                Group(self.user_partition_group_b, 'Group B')
            ])

        # Create course with group configurations and grading policy
        self.course = CourseFactory.create(user_partitions=[self.partition],
                                           grading_policy={
                                               "GRADER": [{
                                                   "type": "Homework",
                                                   "min_count": 1,
                                                   "drop_count": 0,
                                                   "short_label": "HW",
                                                   "weight": 1.0
                                               }]
                                           })
        chapter = ItemFactory.create(parent_location=self.course.location,
                                     display_name='Chapter')

        # add a sequence to the course to which the problems can be added
        self.problem_section = ItemFactory.create(
            parent_location=chapter.location,
            category='sequential',
            metadata={
                'graded': True,
                'format': 'Homework'
            },
            display_name=self.TEST_SECTION_NAME)

        # Create users and partition them
        self.student_a = UserFactory.create(
            username='******', email='student_a@contrived_example.com')
        CourseEnrollmentFactory.create(user=self.student_a,
                                       course_id=self.course.id)
        self.student_b = UserFactory.create(
            username='******', email='student_b@contrived_example.com')
        CourseEnrollmentFactory.create(user=self.student_b,
                                       course_id=self.course.id)

        UserCourseTagFactory(
            user=self.student_a,
            course_id=self.course.id,
            key='xblock.partition_service.partition_{0}'.format(
                self.partition.id),
            value=str(self.user_partition_group_a))
        UserCourseTagFactory(
            user=self.student_b,
            course_id=self.course.id,
            key='xblock.partition_service.partition_{0}'.format(
                self.partition.id),
            value=str(self.user_partition_group_b))

        # Create a vertical to contain our split test
        problem_vertical = ItemFactory.create(
            parent_location=self.problem_section.location,
            category='vertical',
            display_name='Problem Unit')

        # Create the split test and child vertical containers
        vertical_a_url = self.course.id.make_usage_key(
            'vertical', 'split_test_vertical_a')
        vertical_b_url = self.course.id.make_usage_key(
            'vertical', 'split_test_vertical_b')
        self.split_test = ItemFactory.create(
            parent_location=problem_vertical.location,
            category='split_test',
            display_name='Split Test',
            user_partition_id=self.partition.id,
            group_id_to_child={
                str(index): url
                for index, url in enumerate([vertical_a_url, vertical_b_url])
            })
        self.vertical_a = ItemFactory.create(
            parent_location=self.split_test.location,
            category='vertical',
            display_name='Group A problem container',
            location=vertical_a_url)
        self.vertical_b = ItemFactory.create(
            parent_location=self.split_test.location,
            category='vertical',
            display_name='Group B problem container',
            location=vertical_b_url)
Example #59
0
 def _create_enrollments(self, *course_ids):
     """Variadic helper used to create course enrollments."""
     for course_id in course_ids:
         CourseEnrollmentFactory(user=self.user, course_id=course_id)
Example #60
0
    def test_unfulfilled_entitlement(self, mock_course_overview,
                                     mock_pseudo_session, mock_course_runs,
                                     mock_get_programs):
        """
        When a learner has an unfulfilled entitlement, their course dashboard should have:
            - a hidden 'View Course' button
            - the text 'In order to view the course you must select a session:'
            - an unhidden course-entitlement-selection-container
            - a related programs message
        """
        program = ProgramFactory()
        CourseEntitlementFactory.create(
            user=self.user, course_uuid=program['courses'][0]['uuid'])
        mock_get_programs.return_value = [program]
        course_key = CourseKey.from_string('course-v1:FAKE+FA1-MA1.X+3T2017')
        mock_course_overview.return_value = CourseOverviewFactory.create(
            start=self.TOMORROW, id=course_key)
        mock_course_runs.return_value = [{
            'key': six.text_type(course_key),
            'enrollment_end': str(self.TOMORROW),
            'pacing_type': 'instructor_paced',
            'type': 'verified',
            'status': 'published'
        }]
        mock_pseudo_session.return_value = {
            'key': six.text_type(course_key),
            'type': 'verified'
        }
        response = self.client.get(self.path)
        self.assertContains(response,
                            'class="course-target-link enter-course hidden"')
        self.assertContains(response,
                            'You must select a session to access the course.')
        self.assertContains(
            response, '<div class="course-entitlement-selection-container ">')
        self.assertContains(response, 'Related Programs:')

        # If an entitlement has already been redeemed by the user for a course run, do not let the run be selectable
        enrollment = CourseEnrollmentFactory(
            user=self.user,
            course_id=six.text_type(mock_course_overview.return_value.id),
            mode=CourseMode.VERIFIED)
        CourseEntitlementFactory.create(
            user=self.user,
            course_uuid=program['courses'][0]['uuid'],
            enrollment_course_run=enrollment)

        mock_course_runs.return_value = [{
            'key': 'course-v1:edX+toy+2012_Fall',
            'enrollment_end': str(self.TOMORROW),
            'pacing_type': 'instructor_paced',
            'type': 'verified',
            'status': 'published'
        }]
        response = self.client.get(self.path)
        # There should be two entitlements on the course page, one prompting for a mandatory session, but no
        # select option for the courses as there is only the single course run which has already been redeemed
        self.assertContains(response, '<li class="course-item">', count=2)
        self.assertContains(response,
                            'You must select a session to access the course.')
        self.assertNotContains(response,
                               'To access the course, select a session.')