class CertificateDisplayTest(ModuleStoreTestCase):
    """Tests display of certificates on the student dashboard. """

    USERNAME = "******"
    PASSWORD = "******"
    DOWNLOAD_URL = "http://www.example.com/certificate.pdf"

    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):
        self._create_certificate(enrollment_mode)
        self._check_can_download_certificate()

    @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False})
    def test_display_verified_certificate_no_id(self):
        """
        Confirm that if we get a certificate with a no-id-professional mode
        we still can download our certificate
        """
        self._create_certificate(CourseMode.NO_ID_PROFESSIONAL_MODE)
        self._check_can_download_certificate_no_id()

    @ddt.data('verified', 'honor')
    @override_settings(CERT_NAME_SHORT='Test_Certificate')
    @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
    def test_display_download_certificate_button(self, enrollment_mode):
        """
        Tests if CERTIFICATES_HTML_VIEW is True
        and course has enabled web certificates via cert_html_view_enabled setting
        and no active certificate configuration available
        then any of the Download certificate button should not be visible.
        """
        self.course.cert_html_view_enabled = True
        self.course.save()
        self.store.update_item(self.course, self.user.id)
        self._create_certificate(enrollment_mode)
        self._check_can_not_download_certificate()

    @ddt.data('verified')
    @override_settings(CERT_NAME_SHORT='Test_Certificate')
    @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
    def test_linked_student_to_web_view_credential(self, enrollment_mode):
        test_url = get_certificate_url(
            user_id=self.user.id,
            course_id=unicode(self.course.id)
        )

        self._create_certificate(enrollment_mode)
        certificates = [
            {
                'id': 0,
                'name': 'Test Name',
                'description': 'Test Description',
                'is_active': True,
                'signatories': [],
                'version': 1
            }
        ]
        self.course.certificates = {'certificates': certificates}
        self.course.cert_html_view_enabled = True
        self.course.save()   # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)

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

        self.assertContains(response, u'View Test_Certificate')
        self.assertContains(response, test_url)

    def _create_certificate(self, enrollment_mode):
        """Simulate that the user has a generated certificate. """
        CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, mode=enrollment_mode)
        GeneratedCertificateFactory(
            user=self.user,
            course_id=self.course.id,
            mode=enrollment_mode,
            download_url=self.DOWNLOAD_URL,
            status="downloadable",
            grade=0.98,
        )

    def _check_can_download_certificate(self):
        response = self.client.get(reverse('dashboard'))
        self.assertContains(response, u'Download Your ID Verified')
        self.assertContains(response, self.DOWNLOAD_URL)

    def _check_can_download_certificate_no_id(self):
        """
        Inspects the dashboard to see if a certificate for a non verified course enrollment
        is present
        """
        response = self.client.get(reverse('dashboard'))
        self.assertContains(response, u'Download')
        self.assertContains(response, u'(PDF)')
        self.assertContains(response, self.DOWNLOAD_URL)

    def _check_can_not_download_certificate(self):
        """
        Make sure response does not have any of the download certificate buttons
        """
        response = self.client.get(reverse('dashboard'))
        self.assertNotContains(response, u'View Test_Certificate')
        self.assertNotContains(response, u'Download Your Test_Certificate (PDF)')
        self.assertNotContains(response, u'Download Test_Certificate (PDF)')
        self.assertNotContains(response, self.DOWNLOAD_URL)
Exemple #2
0
class CertificateSearchTests(ModuleStoreTestCase, CertificateSupportTestCase):
    """
    Tests for the certificate search end-point used by the support team.
    """
    def setUp(self):
        """
        Create a course
        """
        super(CertificateSearchTests, self).setUp()
        self.course = CourseFactory()
        self.course.cert_html_view_enabled = True

        #course certificate configurations
        certificates = [{
            'id': 1,
            'name': 'Name 1',
            'description': 'Description 1',
            'course_title': 'course_title_1',
            'signatories': [],
            'version': 1,
            'is_active': True
        }]

        self.course.certificates = {'certificates': certificates}
        self.course.save()  # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)

    @ddt.data(
        (GlobalStaff, True),
        (SupportStaffRole, True),
        (None, False),
    )
    @ddt.unpack
    def test_access_control(self, role, has_access):
        # Create a user and log in
        user = UserFactory(username="******", password="******")
        success = self.client.login(username="******", password="******")
        self.assertTrue(success, msg="Could not log in")

        # Assign the user to the role
        if role is not None:
            role().add_users(user)

        # Retrieve the page
        response = self._search("foo")

        if has_access:
            self.assertContains(response, json.dumps([]))
        else:
            self.assertEqual(response.status_code, 403)

    @ddt.data(
        (CertificateSupportTestCase.STUDENT_USERNAME, True),
        (CertificateSupportTestCase.STUDENT_EMAIL, True),
        ("bar", False),
        ("*****@*****.**", False),
    )
    @ddt.unpack
    def test_search(self, query, expect_result):
        response = self._search(query)
        self.assertEqual(response.status_code, 200)

        results = json.loads(response.content)
        self.assertEqual(len(results), 1 if expect_result else 0)

    def test_results(self):
        response = self._search(self.STUDENT_USERNAME)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content)

        self.assertEqual(len(results), 1)
        retrieved_cert = results[0]

        self.assertEqual(retrieved_cert["username"], self.STUDENT_USERNAME)
        self.assertEqual(retrieved_cert["course_key"],
                         unicode(self.CERT_COURSE_KEY))
        self.assertEqual(retrieved_cert["created"],
                         self.cert.created_date.isoformat())
        self.assertEqual(retrieved_cert["modified"],
                         self.cert.modified_date.isoformat())
        self.assertEqual(retrieved_cert["grade"], unicode(self.CERT_GRADE))
        self.assertEqual(retrieved_cert["status"], self.CERT_STATUS)
        self.assertEqual(retrieved_cert["type"], self.CERT_MODE)
        self.assertEqual(retrieved_cert["download_url"],
                         self.CERT_DOWNLOAD_URL)

    @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
    def test_download_link(self):
        self.cert.course_id = self.course.id  # pylint: disable=no-member
        self.cert.download_url = ''
        self.cert.save()

        response = self._search(self.STUDENT_USERNAME)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content)

        self.assertEqual(len(results), 1)
        retrieved_cert = results[0]

        self.assertEqual(
            retrieved_cert["download_url"],
            reverse(
                'certificates:html_view',
                kwargs={
                    "user_id": self.student.id,
                    "course_id": self.course.id
                }  # pylint: disable=no-member
            ))

    def _search(self, query):
        """Execute a search and return the response. """
        url = reverse("certificates:search") + "?query=" + query
        return self.client.get(url)
Exemple #3
0
class CertificateSearchTests(CertificateSupportTestCase):
    """
    Tests for the certificate search end-point used by the support team.
    """
    def setUp(self):
        """
        Create a course
        """
        super().setUp()
        self.course = CourseFactory(
            org=self.CERT_COURSE_KEY.org,
            course=self.CERT_COURSE_KEY.course,
            run=self.CERT_COURSE_KEY.run,
        )
        self.course.cert_html_view_enabled = True
        self.course_key = self.course.id  # pylint: disable=no-member

        # Course certificate configurations
        certificates = [{
            'id': 1,
            'name': 'Name 1',
            'description': 'Description 1',
            'course_title': 'course_title_1',
            'signatories': [],
            'version': 1,
            'is_active': True
        }]

        self.course.certificates = {'certificates': certificates}
        self.course.save()  # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)
        self.course_overview = CourseOverviewFactory(
            id=self.course_key,
            cert_html_view_enabled=True,
        )

    @ddt.data(
        (GlobalStaff, True),
        (SupportStaffRole, True),
        (None, False),
    )
    @ddt.unpack
    def test_access_control(self, role, has_access):
        # Create a user and log in
        user = UserFactory(username="******", password="******")
        success = self.client.login(username="******", password="******")
        assert success, 'Could not log in'

        # Assign the user to the role
        if role is not None:
            role().add_users(user)

        # Retrieve the page
        response = self._search("foo")

        if has_access:
            self.assertContains(response, json.dumps([]))
        else:
            assert response.status_code == 403

    @ddt.data(
        (CertificateSupportTestCase.STUDENT_USERNAME, True),
        (CertificateSupportTestCase.STUDENT_EMAIL, True),
        ("bar", False),
        ("*****@*****.**", False),
        ("", False),
        (CertificateSupportTestCase.STUDENT_USERNAME, False, 'invalid_key'),
        (CertificateSupportTestCase.STUDENT_USERNAME, False,
         str(CertificateSupportTestCase.COURSE_NOT_EXIST_KEY)),
        (CertificateSupportTestCase.STUDENT_USERNAME, True,
         str(CertificateSupportTestCase.EXISTED_COURSE_KEY_1)),
    )
    @ddt.unpack
    def test_search(self, user_filter, expect_result, course_filter=None):
        response = self._search(user_filter, course_filter)
        if expect_result:
            assert response.status_code == 200
            results = json.loads(response.content.decode('utf-8'))
            assert len(results) == 1
        else:
            assert response.status_code == 400

    def test_search_with_plus_sign(self):
        """
        Test that email address that contains '+' accepted by student support
        """
        self.student.email = "*****@*****.**"
        self.student.save()

        response = self._search(self.student.email)
        assert response.status_code == 200
        results = json.loads(response.content.decode('utf-8'))

        assert len(results) == 1
        retrieved_data = results[0]
        assert retrieved_data['username'] == self.STUDENT_USERNAME

    def test_results(self):
        response = self._search(self.STUDENT_USERNAME)
        assert response.status_code == 200
        results = json.loads(response.content.decode('utf-8'))

        assert len(results) == 1
        retrieved_cert = results[0]

        assert retrieved_cert['username'] == self.STUDENT_USERNAME
        assert retrieved_cert['course_key'] == str(self.CERT_COURSE_KEY)
        assert retrieved_cert['created'] == self.cert.created_date.isoformat()
        assert retrieved_cert['modified'] == self.cert.modified_date.isoformat(
        )
        assert retrieved_cert['grade'] == str(self.CERT_GRADE)
        assert retrieved_cert['status'] == self.CERT_STATUS
        assert retrieved_cert['type'] == self.CERT_MODE
        assert retrieved_cert['download_url'] == self.CERT_DOWNLOAD_URL
        assert not retrieved_cert['regenerate']

    @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
    def test_download_link(self):
        self.cert.course_id = self.course_key
        self.cert.download_url = ''
        self.cert.save()

        response = self._search(self.STUDENT_USERNAME)
        assert response.status_code == 200
        results = json.loads(response.content.decode('utf-8'))

        assert len(results) == 1
        retrieved_cert = results[0]

        assert retrieved_cert['download_url'] ==\
               reverse('certificates:render_cert_by_uuid',
                       kwargs={'certificate_uuid': self.cert.verify_uuid})
        assert retrieved_cert['regenerate']

    def _search(self, user_filter, course_filter=None):
        """Execute a search and return the response. """
        url = reverse("certificates:search") + "?user=" + user_filter
        if course_filter:
            url += '&course_id=' + course_filter
        return self.client.get(url)
Exemple #4
0
class CertificateDisplayTest(ModuleStoreTestCase):
    """Tests display of certificates on the student dashboard. """

    USERNAME = "******"
    PASSWORD = "******"
    DOWNLOAD_URL = "http://www.example.com/certificate.pdf"

    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):
        self._create_certificate(enrollment_mode)
        self._check_can_download_certificate()

    @ddt.data('verified', 'honor')
    @override_settings(CERT_NAME_SHORT='Test_Certificate')
    @patch.dict('django.conf.settings.FEATURES',
                {'CERTIFICATES_HTML_VIEW': True})
    def test_display_download_certificate_button(self, enrollment_mode):
        """
        Tests if CERTIFICATES_HTML_VIEW is True
        and course has enabled web certificates via cert_html_view_enabled setting
        and no active certificate configuration available
        then any of the Download certificate button should not be visible.
        """
        self.course.cert_html_view_enabled = True
        self.course.save()
        self.store.update_item(self.course, self.user.id)
        self._create_certificate(enrollment_mode)
        self._check_can_not_download_certificate()

    @ddt.data('verified')
    @override_settings(CERT_NAME_SHORT='Test_Certificate')
    @patch.dict('django.conf.settings.FEATURES',
                {'CERTIFICATES_HTML_VIEW': True})
    def test_linked_student_to_web_view_credential(self, enrollment_mode):
        test_url = get_certificate_url(user_id=self.user.id,
                                       course_id=unicode(self.course.id),
                                       verify_uuid='abcdefg12345678')

        self._create_certificate(enrollment_mode)
        certificates = [{
            'id': 0,
            'name': 'Test Name',
            'description': 'Test Description',
            'is_active': True,
            'signatories': [],
            'version': 1
        }]
        self.course.certificates = {'certificates': certificates}
        self.course.cert_html_view_enabled = True
        self.course.save()  # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)

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

        self.assertContains(response, u'View Test_Certificate')
        self.assertContains(response, test_url)

    def _create_certificate(self, enrollment_mode):
        """Simulate that the user has a generated certificate. """
        CourseEnrollmentFactory.create(user=self.user,
                                       course_id=self.course.id,
                                       mode=enrollment_mode)
        GeneratedCertificateFactory(
            user=self.user,
            course_id=self.course.id,
            mode=enrollment_mode,
            download_url=self.DOWNLOAD_URL,
            status="downloadable",
            grade=0.98,
        )

    def _check_can_download_certificate(self):
        response = self.client.get(reverse('dashboard'))
        self.assertContains(response, u'Download Your ID Verified')
        self.assertContains(response, self.DOWNLOAD_URL)

    def _check_can_not_download_certificate(self):
        """
        Make sure response does not have any of the download certificate buttons
        """
        response = self.client.get(reverse('dashboard'))
        self.assertNotContains(response, u'View Test_Certificate')
        self.assertNotContains(response,
                               u'Download Your Test_Certificate (PDF)')
        self.assertNotContains(response, u'Download Test_Certificate (PDF)')
        self.assertNotContains(response, self.DOWNLOAD_URL)
Exemple #5
0
class CertificateSearchTests(CertificateSupportTestCase):
    """
    Tests for the certificate search end-point used by the support team.
    """

    def setUp(self):
        """
        Create a course
        """
        super(CertificateSearchTests, self).setUp()
        self.course = CourseFactory(
            org=self.CERT_COURSE_KEY.org,
            course=self.CERT_COURSE_KEY.course,
            run=self.CERT_COURSE_KEY.run,
        )
        self.course.cert_html_view_enabled = True

        #course certificate configurations
        certificates = [
            {
                'id': 1,
                'name': 'Name 1',
                'description': 'Description 1',
                'course_title': 'course_title_1',
                'signatories': [],
                'version': 1,
                'is_active': True
            }
        ]

        self.course.certificates = {'certificates': certificates}
        self.course.save()
        self.store.update_item(self.course, self.user.id)
        self.course_overview = CourseOverviewFactory(
            id=self.course.id,
            cert_html_view_enabled=True,
        )

    @ddt.data(
        (GlobalStaff, True),
        (SupportStaffRole, True),
        (None, False),
    )
    @ddt.unpack
    def test_access_control(self, role, has_access):
        # Create a user and log in
        user = UserFactory(username="******", password="******")
        success = self.client.login(username="******", password="******")
        self.assertTrue(success, msg="Could not log in")

        # Assign the user to the role
        if role is not None:
            role().add_users(user)

        # Retrieve the page
        response = self._search("foo")

        if has_access:
            self.assertContains(response, json.dumps([]))
        else:
            self.assertEqual(response.status_code, 403)

    @ddt.data(
        (CertificateSupportTestCase.STUDENT_USERNAME, True),
        (CertificateSupportTestCase.STUDENT_EMAIL, True),
        ("bar", False),
        ("*****@*****.**", False),
        ("", False),
        (CertificateSupportTestCase.STUDENT_USERNAME, False, 'invalid_key'),
        (CertificateSupportTestCase.STUDENT_USERNAME, False,
            six.text_type(CertificateSupportTestCase.COURSE_NOT_EXIST_KEY)),
        (CertificateSupportTestCase.STUDENT_USERNAME, True,
            six.text_type(CertificateSupportTestCase.EXISTED_COURSE_KEY_1)),
    )
    @ddt.unpack
    def test_search(self, user_filter, expect_result, course_filter=None):
        response = self._search(user_filter, course_filter)
        if expect_result:
            self.assertEqual(response.status_code, 200)
            results = json.loads(response.content.decode('utf-8'))
            self.assertEqual(len(results), 1)
        else:
            self.assertEqual(response.status_code, 400)

    def test_search_with_plus_sign(self):
        """
        Test that email address that contains '+' accepted by student support
        """
        self.student.email = "*****@*****.**"
        self.student.save()

        response = self._search(self.student.email)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content.decode('utf-8'))

        self.assertEqual(len(results), 1)
        retrieved_data = results[0]
        self.assertEqual(retrieved_data["username"], self.STUDENT_USERNAME)

    def test_results(self):
        response = self._search(self.STUDENT_USERNAME)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content.decode('utf-8'))

        self.assertEqual(len(results), 1)
        retrieved_cert = results[0]

        self.assertEqual(retrieved_cert["username"], self.STUDENT_USERNAME)
        self.assertEqual(retrieved_cert["course_key"], six.text_type(self.CERT_COURSE_KEY))
        self.assertEqual(retrieved_cert["created"], self.cert.created_date.isoformat())
        self.assertEqual(retrieved_cert["modified"], self.cert.modified_date.isoformat())
        self.assertEqual(retrieved_cert["grade"], six.text_type(self.CERT_GRADE))
        self.assertEqual(retrieved_cert["status"], self.CERT_STATUS)
        self.assertEqual(retrieved_cert["type"], self.CERT_MODE)
        self.assertEqual(retrieved_cert["download_url"], self.CERT_DOWNLOAD_URL)
        self.assertFalse(retrieved_cert["regenerate"])

    @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
    def test_download_link(self):
        self.cert.course_id = self.course.id
        self.cert.download_url = ''
        self.cert.save()

        response = self._search(self.STUDENT_USERNAME)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content.decode('utf-8'))

        self.assertEqual(len(results), 1)
        retrieved_cert = results[0]

        self.assertEqual(
            retrieved_cert["download_url"],
            reverse(
                'certificates:html_view',
                kwargs={"user_id": self.student.id, "course_id": self.course.id}
            )
        )
        self.assertTrue(retrieved_cert["regenerate"])

    def _search(self, user_filter, course_filter=None):
        """Execute a search and return the response. """
        url = reverse("certificates:search") + "?user=" + user_filter
        if course_filter:
            url += '&course_id=' + course_filter
        return self.client.get(url)
class CertificateSearchTests(CertificateSupportTestCase):
    """
    Tests for the certificate search end-point used by the support team.
    """
    def setUp(self):
        """
        Create a course
        """
        super(CertificateSearchTests, self).setUp()
        self.course = CourseFactory()
        self.course.cert_html_view_enabled = True

        #course certificate configurations
        certificates = [
            {
                'id': 1,
                'name': 'Name 1',
                'description': 'Description 1',
                'course_title': 'course_title_1',
                'signatories': [],
                'version': 1,
                'is_active': True
            }
        ]

        self.course.certificates = {'certificates': certificates}
        self.course.save()  # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)

    @ddt.data(
        (GlobalStaff, True),
        (SupportStaffRole, True),
        (None, False),
    )
    @ddt.unpack
    def test_access_control(self, role, has_access):
        # Create a user and log in
        user = UserFactory(username="******", password="******")
        success = self.client.login(username="******", password="******")
        self.assertTrue(success, msg="Could not log in")

        # Assign the user to the role
        if role is not None:
            role().add_users(user)

        # Retrieve the page
        response = self._search("foo")

        if has_access:
            self.assertContains(response, json.dumps([]))
        else:
            self.assertEqual(response.status_code, 403)

    @ddt.data(
        (CertificateSupportTestCase.STUDENT_USERNAME, True),
        (CertificateSupportTestCase.STUDENT_EMAIL, True),
        ("bar", False),
        ("*****@*****.**", False),
        ("", False),
        (CertificateSupportTestCase.STUDENT_USERNAME, False, 'invalid_key'),
        (CertificateSupportTestCase.STUDENT_USERNAME, False, unicode(CertificateSupportTestCase.COURSE_NOT_EXIST_KEY)),
        (CertificateSupportTestCase.STUDENT_USERNAME, True, unicode(CertificateSupportTestCase.EXISTED_COURSE_KEY_1)),
    )
    @ddt.unpack
    def test_search(self, user_filter, expect_result, course_filter=None):
        response = self._search(user_filter, course_filter)
        if expect_result:
            self.assertEqual(response.status_code, 200)
            results = json.loads(response.content)
            self.assertEqual(len(results), 1)
        else:
            self.assertEqual(response.status_code, 400)

    def test_search_with_plus_sign(self):
        """
        Test that email address that contains '+' accepted by student support
        """
        self.student.email = "*****@*****.**"
        self.student.save()  # pylint: disable=no-member

        response = self._search(self.student.email)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content)

        self.assertEqual(len(results), 1)
        retrieved_data = results[0]
        self.assertEqual(retrieved_data["username"], self.STUDENT_USERNAME)

    def test_results(self):
        response = self._search(self.STUDENT_USERNAME)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content)

        self.assertEqual(len(results), 1)
        retrieved_cert = results[0]

        self.assertEqual(retrieved_cert["username"], self.STUDENT_USERNAME)
        self.assertEqual(retrieved_cert["course_key"], unicode(self.CERT_COURSE_KEY))
        self.assertEqual(retrieved_cert["created"], self.cert.created_date.isoformat())
        self.assertEqual(retrieved_cert["modified"], self.cert.modified_date.isoformat())
        self.assertEqual(retrieved_cert["grade"], unicode(self.CERT_GRADE))
        self.assertEqual(retrieved_cert["status"], self.CERT_STATUS)
        self.assertEqual(retrieved_cert["type"], self.CERT_MODE)
        self.assertEqual(retrieved_cert["download_url"], self.CERT_DOWNLOAD_URL)

    @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
    def test_download_link(self):
        self.cert.course_id = self.course.id  # pylint: disable=no-member
        self.cert.download_url = ''
        self.cert.save()

        response = self._search(self.STUDENT_USERNAME)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content)

        self.assertEqual(len(results), 1)
        retrieved_cert = results[0]

        self.assertEqual(
            retrieved_cert["download_url"],
            reverse(
                'certificates:html_view',
                kwargs={"user_id": self.student.id, "course_id": self.course.id}  # pylint: disable=no-member
            )
        )

    def _search(self, user_filter, course_filter=None):
        """Execute a search and return the response. """
        url = reverse("certificates:search") + "?user=" + user_filter
        if course_filter:
            url += '&course_id=' + course_filter
        return self.client.get(url)
class CertificateSearchTests(ModuleStoreTestCase, CertificateSupportTestCase):
    """
    Tests for the certificate search end-point used by the support team.
    """

    def setUp(self):
        """
        Create a course
        """
        super(CertificateSearchTests, self).setUp()
        self.course = CourseFactory()
        self.course.cert_html_view_enabled = True

        # course certificate configurations
        certificates = [
            {
                "id": 1,
                "name": "Name 1",
                "description": "Description 1",
                "course_title": "course_title_1",
                "signatories": [],
                "version": 1,
                "is_active": True,
            }
        ]

        self.course.certificates = {"certificates": certificates}
        self.course.save()  # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)

    @ddt.data((GlobalStaff, True), (SupportStaffRole, True), (None, False))
    @ddt.unpack
    def test_access_control(self, role, has_access):
        # Create a user and log in
        user = UserFactory(username="******", password="******")
        success = self.client.login(username="******", password="******")
        self.assertTrue(success, msg="Could not log in")

        # Assign the user to the role
        if role is not None:
            role().add_users(user)

        # Retrieve the page
        response = self._search("foo")

        if has_access:
            self.assertContains(response, json.dumps([]))
        else:
            self.assertEqual(response.status_code, 403)

    @ddt.data(
        (CertificateSupportTestCase.STUDENT_USERNAME, True),
        (CertificateSupportTestCase.STUDENT_EMAIL, True),
        ("bar", False),
        ("*****@*****.**", False),
    )
    @ddt.unpack
    def test_search(self, query, expect_result):
        response = self._search(query)
        self.assertEqual(response.status_code, 200)

        results = json.loads(response.content)
        self.assertEqual(len(results), 1 if expect_result else 0)

    def test_results(self):
        response = self._search(self.STUDENT_USERNAME)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content)

        self.assertEqual(len(results), 1)
        retrieved_cert = results[0]

        self.assertEqual(retrieved_cert["username"], self.STUDENT_USERNAME)
        self.assertEqual(retrieved_cert["course_key"], unicode(self.CERT_COURSE_KEY))
        self.assertEqual(retrieved_cert["created"], self.cert.created_date.isoformat())
        self.assertEqual(retrieved_cert["modified"], self.cert.modified_date.isoformat())
        self.assertEqual(retrieved_cert["grade"], unicode(self.CERT_GRADE))
        self.assertEqual(retrieved_cert["status"], self.CERT_STATUS)
        self.assertEqual(retrieved_cert["type"], self.CERT_MODE)
        self.assertEqual(retrieved_cert["download_url"], self.CERT_DOWNLOAD_URL)

    @override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
    def test_download_link(self):
        self.cert.course_id = self.course.id  # pylint: disable=no-member
        self.cert.download_url = ""
        self.cert.save()

        response = self._search(self.STUDENT_USERNAME)
        self.assertEqual(response.status_code, 200)
        results = json.loads(response.content)

        self.assertEqual(len(results), 1)
        retrieved_cert = results[0]

        self.assertEqual(
            retrieved_cert["download_url"],
            reverse(
                "certificates:html_view",
                kwargs={"user_id": self.student.id, "course_id": self.course.id},  # pylint: disable=no-member
            ),
        )

    def _search(self, query):
        """Execute a search and return the response. """
        url = reverse("certificates:search") + "?query=" + query
        return self.client.get(url)
class CertificateDisplayTest(ModuleStoreTestCase):
    """Tests display of certificates on the student dashboard. """

    USERNAME = "******"
    PASSWORD = "******"
    DOWNLOAD_URL = "http://www.example.com/certificate.pdf"

    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):
        self._create_certificate(enrollment_mode)
        self._check_can_download_certificate()

    @ddt.data("verified", "honor")
    @override_settings(CERT_NAME_SHORT="Test_Certificate")
    @patch.dict("django.conf.settings.FEATURES", {"CERTIFICATES_HTML_VIEW": True})
    def test_display_download_certificate_button(self, enrollment_mode):
        """
        Tests if CERTIFICATES_HTML_VIEW is True
        and course has enabled web certificates via cert_html_view_enabled setting
        and no active certificate configuration available
        then any of the Download certificate button should not be visible.
        """
        self.course.cert_html_view_enabled = True
        self.course.save()
        self.store.update_item(self.course, self.user.id)
        self._create_certificate(enrollment_mode)
        self._check_can_not_download_certificate()

    @ddt.data("verified")
    @override_settings(CERT_NAME_SHORT="Test_Certificate")
    @patch.dict("django.conf.settings.FEATURES", {"CERTIFICATES_HTML_VIEW": True})
    def test_linked_student_to_web_view_credential(self, enrollment_mode):
        test_url = get_certificate_url(
            user_id=self.user.id, course_id=unicode(self.course.id), verify_uuid="abcdefg12345678"
        )

        self._create_certificate(enrollment_mode)
        certificates = [
            {
                "id": 0,
                "name": "Test Name",
                "description": "Test Description",
                "is_active": True,
                "signatories": [],
                "version": 1,
            }
        ]
        self.course.certificates = {"certificates": certificates}
        self.course.cert_html_view_enabled = True
        self.course.save()  # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)

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

        self.assertContains(response, u"View Test_Certificate")
        self.assertContains(response, test_url)

    def _create_certificate(self, enrollment_mode):
        """Simulate that the user has a generated certificate. """
        CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, mode=enrollment_mode)
        GeneratedCertificateFactory(
            user=self.user,
            course_id=self.course.id,
            mode=enrollment_mode,
            download_url=self.DOWNLOAD_URL,
            status="downloadable",
            grade=0.98,
        )

    def _check_can_download_certificate(self):
        response = self.client.get(reverse("dashboard"))
        self.assertContains(response, u"Download Your ID Verified")
        self.assertContains(response, self.DOWNLOAD_URL)

    def _check_can_not_download_certificate(self):
        """
        Make sure response does not have any of the download certificate buttons
        """
        response = self.client.get(reverse("dashboard"))
        self.assertNotContains(response, u"View Test_Certificate")
        self.assertNotContains(response, u"Download Your Test_Certificate (PDF)")
        self.assertNotContains(response, u"Download Test_Certificate (PDF)")
        self.assertNotContains(response, self.DOWNLOAD_URL)
class CertificateDisplayTest(ModuleStoreTestCase):
    """Tests display of certificates on the student dashboard. """

    USERNAME = "******"
    PASSWORD = "******"
    DOWNLOAD_URL = "http://www.example.com/certificate.pdf"

    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):
        self._create_certificate(enrollment_mode)
        self._check_can_download_certificate()

    @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False})
    def test_display_verified_certificate_no_id(self):
        """
        Confirm that if we get a certificate with a no-id-professional mode
        we still can download our certificate
        """
        self._create_certificate(CourseMode.NO_ID_PROFESSIONAL_MODE)
        self._check_can_download_certificate_no_id()

    @ddt.data('verified', 'honor')
    @override_settings(CERT_NAME_SHORT='Test_Certificate')
    @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
    def test_display_download_certificate_button(self, enrollment_mode):
        """
        Tests if CERTIFICATES_HTML_VIEW is True
        and course has enabled web certificates via cert_html_view_enabled setting
        and no active certificate configuration available
        then any of the Download certificate button should not be visible.
        """
        self.course.cert_html_view_enabled = True
        self.course.save()
        self.store.update_item(self.course, self.user.id)
        self._create_certificate(enrollment_mode)
        self._check_can_not_download_certificate()

    @ddt.data('verified')
    @override_settings(CERT_NAME_SHORT='Test_Certificate')
    @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
    def test_linked_student_to_web_view_credential(self, enrollment_mode):
        cert = self._create_certificate(enrollment_mode)
        test_url = get_certificate_url(uuid=cert.verify_uuid)

        certificates = [
            {
                'id': 0,
                'name': 'Test Name',
                'description': 'Test Description',
                'is_active': True,
                'signatories': [],
                'version': 1
            }
        ]
        self.course.certificates = {'certificates': certificates}
        self.course.cert_html_view_enabled = True
        self.course.save()   # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)

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

        self.assertContains(response, u'View Test_Certificate')
        self.assertContains(response, test_url)

    def test_post_to_linkedin_invisibility(self):
        """
        Verifies that the post certificate to linked button
        does not appear by default (when config is not set)
        """
        self._create_certificate('honor')

        # until we set up the configuration, the LinkedIn action
        # button should not be visible
        self._check_linkedin_visibility(False)

    def test_post_to_linkedin_visibility(self):
        """
        Verifies that the post certificate to linked button appears
        as expected
        """
        self._create_certificate('honor')

        config = LinkedInAddToProfileConfiguration(
            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
            enabled=True
        )
        config.save()

        # now we should see it
        self._check_linkedin_visibility(True)

    @mock.patch("microsite_configuration.microsite.is_request_in_microsite", _fake_is_request_in_microsite)
    def test_post_to_linkedin_microsite(self):
        """
        Verifies behavior for microsites which disables the post to LinkedIn
        feature (for now)
        """
        self._create_certificate('honor')

        config = LinkedInAddToProfileConfiguration(
            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
            enabled=True
        )
        config.save()

        # now we should not see it because we are in a microsite
        self._check_linkedin_visibility(False)

    def _check_linkedin_visibility(self, is_visible):
        """
        Performs assertions on the Dashboard
        """
        response = self.client.get(reverse('dashboard'))
        if is_visible:
            self.assertContains(response, u'Add Certificate to LinkedIn Profile')
        else:
            self.assertNotContains(response, u'Add Certificate to LinkedIn Profile')

    def _create_certificate(self, enrollment_mode):
        """Simulate that the user has a generated certificate. """
        CourseEnrollmentFactory.create(user=self.user, course_id=self.course.id, mode=enrollment_mode)
        return GeneratedCertificateFactory(
            user=self.user,
            course_id=self.course.id,
            mode=enrollment_mode,
            download_url=self.DOWNLOAD_URL,
            status="downloadable",
            grade=0.98,
        )

    def _check_can_download_certificate(self):
        response = self.client.get(reverse('dashboard'))
        self.assertContains(response, u'Download Your ID Verified')
        self.assertContains(response, self.DOWNLOAD_URL)

    def _check_can_download_certificate_no_id(self):
        """
        Inspects the dashboard to see if a certificate for a non verified course enrollment
        is present
        """
        response = self.client.get(reverse('dashboard'))
        self.assertContains(response, u'Download')
        self.assertContains(response, u'(PDF)')
        self.assertContains(response, self.DOWNLOAD_URL)

    def _check_can_not_download_certificate(self):
        """
        Make sure response does not have any of the download certificate buttons
        """
        response = self.client.get(reverse('dashboard'))
        self.assertNotContains(response, u'View Test_Certificate')
        self.assertNotContains(response, u'Download Your Test_Certificate (PDF)')
        self.assertNotContains(response, u'Download Test_Certificate (PDF)')
        self.assertNotContains(response, self.DOWNLOAD_URL)
Exemple #10
0
class CertificateDisplayTest(ModuleStoreTestCase):
    """Tests display of certificates on the student dashboard. """

    USERNAME = "******"
    PASSWORD = "******"
    DOWNLOAD_URL = "http://www.example.com/certificate.pdf"

    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):
        self._create_certificate(enrollment_mode)
        self._check_can_download_certificate()

    @patch.dict('django.conf.settings.FEATURES',
                {'CERTIFICATES_HTML_VIEW': False})
    def test_display_verified_certificate_no_id(self):
        """
        Confirm that if we get a certificate with a no-id-professional mode
        we still can download our certificate
        """
        self._create_certificate(CourseMode.NO_ID_PROFESSIONAL_MODE)
        self._check_can_download_certificate_no_id()

    @ddt.data('verified', 'honor')
    @override_settings(CERT_NAME_SHORT='Test_Certificate')
    @patch.dict('django.conf.settings.FEATURES',
                {'CERTIFICATES_HTML_VIEW': True})
    def test_display_download_certificate_button(self, enrollment_mode):
        """
        Tests if CERTIFICATES_HTML_VIEW is True
        and course has enabled web certificates via cert_html_view_enabled setting
        and no active certificate configuration available
        then any of the Download certificate button should not be visible.
        """
        self.course.cert_html_view_enabled = True
        self.course.save()
        self.store.update_item(self.course, self.user.id)
        self._create_certificate(enrollment_mode)
        self._check_can_not_download_certificate()

    @ddt.data('verified')
    @override_settings(CERT_NAME_SHORT='Test_Certificate')
    @patch.dict('django.conf.settings.FEATURES',
                {'CERTIFICATES_HTML_VIEW': True})
    def test_linked_student_to_web_view_credential(self, enrollment_mode):
        certificates = [{
            'id': 0,
            'name': 'Test Name',
            'description': 'Test Description',
            'is_active': True,
            'signatories': [],
            'version': 1
        }]
        self.course.certificates = {'certificates': certificates}
        self.course.cert_html_view_enabled = True
        self.course.save()  # pylint: disable=no-member
        self.store.update_item(self.course, self.user.id)

        cert = self._create_certificate(enrollment_mode)
        test_url = get_certificate_url(course_id=self.course.id,
                                       uuid=cert.verify_uuid)

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

        self.assertContains(response, u'View Test_Certificate')
        self.assertContains(response, test_url)

    def test_post_to_linkedin_invisibility(self):
        """
        Verifies that the post certificate to linked button
        does not appear by default (when config is not set)
        """
        self._create_certificate('honor')

        # until we set up the configuration, the LinkedIn action
        # button should not be visible
        self._check_linkedin_visibility(False)

    def test_post_to_linkedin_visibility(self):
        """
        Verifies that the post certificate to linked button appears
        as expected
        """
        self._create_certificate('honor')

        config = LinkedInAddToProfileConfiguration(
            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
            enabled=True)
        config.save()

        # now we should see it
        self._check_linkedin_visibility(True)

    @mock.patch("microsite_configuration.microsite.is_request_in_microsite",
                _fake_is_request_in_microsite)
    def test_post_to_linkedin_microsite(self):
        """
        Verifies behavior for microsites which disables the post to LinkedIn
        feature (for now)
        """
        self._create_certificate('honor')

        config = LinkedInAddToProfileConfiguration(
            company_identifier='0_mC_o2MizqdtZEmkVXjH4eYwMj4DnkCWrZP_D9',
            enabled=True)
        config.save()

        # now we should not see it because we are in a microsite
        self._check_linkedin_visibility(False)

    def _check_linkedin_visibility(self, is_visible):
        """
        Performs assertions on the Dashboard
        """
        response = self.client.get(reverse('dashboard'))
        if is_visible:
            self.assertContains(response,
                                u'Add Certificate to LinkedIn Profile')
        else:
            self.assertNotContains(response,
                                   u'Add Certificate to LinkedIn Profile')

    def _create_certificate(self, enrollment_mode):
        """Simulate that the user has a generated certificate. """
        CourseEnrollmentFactory.create(user=self.user,
                                       course_id=self.course.id,
                                       mode=enrollment_mode)
        return GeneratedCertificateFactory(
            user=self.user,
            course_id=self.course.id,
            mode=enrollment_mode,
            download_url=self.DOWNLOAD_URL,
            status="downloadable",
            grade=0.98,
        )

    def _check_can_download_certificate(self):
        response = self.client.get(reverse('dashboard'))
        self.assertContains(response, u'Download Your ID Verified')
        self.assertContains(response, self.DOWNLOAD_URL)

    def _check_can_download_certificate_no_id(self):
        """
        Inspects the dashboard to see if a certificate for a non verified course enrollment
        is present
        """
        response = self.client.get(reverse('dashboard'))
        self.assertContains(response, u'Download')
        self.assertContains(response, u'(PDF)')
        self.assertContains(response, self.DOWNLOAD_URL)

    def _check_can_not_download_certificate(self):
        """
        Make sure response does not have any of the download certificate buttons
        """
        response = self.client.get(reverse('dashboard'))
        self.assertNotContains(response, u'View Test_Certificate')
        self.assertNotContains(response,
                               u'Download Your Test_Certificate (PDF)')
        self.assertNotContains(response, u'Download Test_Certificate (PDF)')
        self.assertNotContains(response, self.DOWNLOAD_URL)
class TestDiscussionEnabled(CourseTestCase):
    """
    Test discussion enabled flags functionality in a Unit.
    """
    def setUp(self):
        super().setUp()
        self.course = self.get_test_course()
        self.course_usage_key = self.course.id.make_usage_key("course", self.course.id.run)
        self.non_staff_authed_user_client, _ = self.create_non_staff_authed_user_client()

    def get_test_course(self):
        """
        Create and return a test course
        """
        self.course = CourseFactory(
            org="SHIELD",
            number="SH101",
            name="Introduction to Avengers",
            run="2020_T2",
            modulestore=self.store
        )
        self.chapter = ItemFactory(
            parent_location=self.course.location,
            category="chapter",
            display_name="What is SHIELD?",
            modulestore=self.store
        )
        self.sequential = ItemFactory(
            parent_location=self.chapter.location,
            category="sequential",
            display_name="HQ",
            modulestore=self.store
        )
        self.vertical = ItemFactory(
            parent_location=self.sequential.location,
            category="vertical",
            display_name="Triskelion",
            modulestore=self.store
        )
        self.vertical_1 = ItemFactory(
            parent_location=self.sequential.location,
            category="vertical",
            display_name="Helicarrier",
            modulestore=self.store
        )
        self.course.save()
        return self.course

    def _get_discussion_enabled_status(self, usage_key, client=None):
        """
        Issue a GET request to fetch value of discussion_enabled flag of xblock represented by param:usage_key
        """
        client = client if client is not None else self.client
        url = reverse_usage_url("xblock_handler", usage_key)
        resp = client.get(url, HTTP_ACCEPT="application/json")
        return resp

    def get_discussion_enabled_status(self, xblock, client=None):
        """
        Issue a GET request to fetch value of discussion_enabled flag of param:xblock's
        """
        resp = self._get_discussion_enabled_status(xblock.location, client=client)
        content = json.loads(resp.content.decode("utf-8"))
        return content.get("discussion_enabled", None)

    def set_discussion_enabled_status(self, xblock, value, client=None):
        """
        Issue a POST request to update value of discussion_enabled flag of param:xblock's
        """
        client = client if client is not None else self.client
        xblock_location = xblock.location
        url = reverse_usage_url("xblock_handler", xblock_location)
        resp = client.post(
            url,
            HTTP_ACCEPT="application/json",
            data=json.dumps({"metadata": {"discussion_enabled": value}}),
            content_type="application/json",
        )
        return resp

    def test_discussion_enabled_false_initially(self):
        """
        Tests discussion_enabled flag is False initially for vertical
        """
        self.assertFalse(self.get_discussion_enabled_status(self.vertical))
        self.assertFalse(self.get_discussion_enabled_status(self.vertical_1))

    def test_discussion_enabled_toggle(self):
        """
        Tests discussion_enabled can be toggled.
        """
        self.set_discussion_enabled_status(self.vertical, True)
        self.assertTrue(self.get_discussion_enabled_status(self.vertical))
        self.assertFalse(self.get_discussion_enabled_status(self.vertical_1))

    def test_non_course_author_cannot_get_or_set_discussion_enabled_flag(self):
        """
        Test non course author cannot get/set discussion_enabled flag
        """
        resp = self._get_discussion_enabled_status(self.course_usage_key, self.non_staff_authed_user_client)
        self.assertEqual(resp.status_code, 403)
        # Set call to the API with non authorised user should raise a 403
        resp = self.set_discussion_enabled_status(self.vertical, True, self.non_staff_authed_user_client)
        self.assertEqual(resp.status_code, 403)