Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions common/test/acceptance/pages/lms/instructor_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -1032,17 +1032,32 @@ def add_certificate_exception(self, student, free_text_note):
self.get_selector('#notes').fill(free_text_note)
self.get_selector('#add-exception').click()

self.wait_for_ajax()
self.wait_for(
lambda: student in self.get_selector('div.white-listed-students table tr:last-child td').text,
description='Certificate Exception added to list'
)

def remove_first_certificate_exception(self):
"""
Remove Certificate Exception from the white list.
"""
self.wait_for_element_visibility('#add-exception', 'Add Exception button is visible')
self.get_selector('div.white-listed-students table tr td .delete-exception').first.click()
self.wait_for_ajax()

def click_generate_certificate_exceptions_button(self): # pylint: disable=invalid-name
"""
Click 'Generate Exception Certificates' button in 'Certificates Exceptions' section
"""
self.get_selector('#generate-exception-certificates').click()

def fill_user_name_field(self, student):
"""
Fill username/email field with given text
"""
self.get_selector('#certificate-exception').fill(student)

def click_add_exception_button(self):
"""
Click 'Add Exception' button in 'Certificates Exceptions' section
Expand Down
102 changes: 73 additions & 29 deletions common/test/acceptance/tests/lms/test_lms_instructor_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -661,16 +661,65 @@ def test_certificate_exceptions_section_is_visible(self):

def test_instructor_can_add_certificate_exception(self):
"""
Scenario: On the Certificates tab of the Instructor Dashboard, Instructor can added new certificate
exception to list
Scenario: On the Certificates tab of the Instructor Dashboard, Instructor can add new certificate
exception to list.

Given that I am on the Certificates tab on the Instructor Dashboard
When I fill in student username and click 'Add Exception' button
When I fill in student username and notes fields and click 'Add Exception' button
Then new certificate exception should be visible in certificate exceptions list
"""
notes = 'Test Notes'
# Add a student to Certificate exception list
self.certificates_section.add_certificate_exception(self.user_name, '')
self.certificates_section.add_certificate_exception(self.user_name, notes)
self.assertIn(self.user_name, self.certificates_section.last_certificate_exception.text)
self.assertIn(notes, self.certificates_section.last_certificate_exception.text)
self.assertIn(str(self.user_id), self.certificates_section.last_certificate_exception.text)

# Verify that added exceptions are also synced with backend
# Revisit Page
self.certificates_section.refresh()

# wait for the certificate exception section to render
self.certificates_section.wait_for_certificate_exceptions_section()

# validate certificate exception synced with server is visible in certificate exceptions list
self.assertIn(self.user_name, self.certificates_section.last_certificate_exception.text)
self.assertIn(notes, self.certificates_section.last_certificate_exception.text)
self.assertIn(str(self.user_id), self.certificates_section.last_certificate_exception.text)

def test_instructor_can_remove_certificate_exception(self):
"""
Scenario: On the Certificates tab of the Instructor Dashboard, Instructor can remove added certificate
exceptions from the list.

Given that I am on the Certificates tab on the Instructor Dashboard
When I fill in student username and notes fields and click 'Add Exception' button
Then new certificate exception should be visible in certificate exceptions list
"""
notes = 'Test Notes'
# Add a student to Certificate exception list
self.certificates_section.add_certificate_exception(self.user_name, notes)
self.assertIn(self.user_name, self.certificates_section.last_certificate_exception.text)
self.assertIn(notes, self.certificates_section.last_certificate_exception.text)
self.assertIn(str(self.user_id), self.certificates_section.last_certificate_exception.text)

# Remove Certificate Exception
self.certificates_section.remove_first_certificate_exception()
self.assertNotIn(self.user_name, self.certificates_section.last_certificate_exception.text)
self.assertNotIn(notes, self.certificates_section.last_certificate_exception.text)
self.assertNotIn(str(self.user_id), self.certificates_section.last_certificate_exception.text)

# Verify that added exceptions are also synced with backend
# Revisit Page
self.certificates_section.refresh()

# wait for the certificate exception section to render
self.certificates_section.wait_for_certificate_exceptions_section()

# validate certificate exception synced with server is visible in certificate exceptions list
self.assertNotIn(self.user_name, self.certificates_section.last_certificate_exception.text)
self.assertNotIn(notes, self.certificates_section.last_certificate_exception.text)
self.assertNotIn(str(self.user_id), self.certificates_section.last_certificate_exception.text)

def test_error_on_duplicate_certificate_exception(self):
"""
Expand Down Expand Up @@ -711,51 +760,46 @@ def test_error_on_empty_user_name(self):
self.certificates_section.message.text
)

def test_generate_certificate_exception(self):
def test_error_on_non_existing_user(self):
"""
Scenario: On the Certificates tab of the Instructor Dashboard, when user clicks
'Generate Exception Certificates' newly added certificate exceptions should be synced on server
Scenario: On the Certificates tab of the Instructor Dashboard,
Error message appears if username/email does not exists in the system while clicking "Add Exception" button

Given that I am on the Certificates tab on the Instructor Dashboard
When I click 'Generate Exception Certificates'
Then newly added certificate exceptions should be synced on server
When I click on 'Add Exception' button
AND student username/email does not exists
Then Error Message should say 'Student username/email is required.'
"""
# Add a student to Certificate exception list
self.certificates_section.add_certificate_exception(self.user_name, '')
invalid_user = 'test_user_non_existent'
# Click 'Add Exception' button with invalid username/email field
self.certificates_section.wait_for_certificate_exceptions_section()

# Click 'Generate Exception Certificates' button
self.certificates_section.click_generate_certificate_exceptions_button()
self.certificates_section.fill_user_name_field(invalid_user)
self.certificates_section.click_add_exception_button()
self.certificates_section.wait_for_ajax()

# Revisit Page
self.certificates_section.refresh()

# wait for the certificate exception section to render
self.certificates_section.wait_for_certificate_exceptions_section()

# validate certificate exception synced with server is visible in certificate exceptions list
self.assertIn(self.user_name, self.certificates_section.last_certificate_exception.text)
self.assertIn(
'Student (username/email={}) does not exist'.format(invalid_user),
self.certificates_section.message.text
)

def test_invalid_user_on_generate_certificate_exception(self):
def test_generate_certificate_exception(self):
"""
Scenario: On the Certificates tab of the Instructor Dashboard, when user clicks
'Generate Exception Certificates' error message should appear if user does not exist
'Generate Exception Certificates' newly added certificate exceptions should be synced on server

Given that I am on the Certificates tab on the Instructor Dashboard
When I click 'Generate Exception Certificates'
AND the user specified by instructor does not exist
Then an error message "Student (username/email=test_user) does not exist" is displayed
Then newly added certificate exceptions should be synced on server
"""
invalid_user = 'test_user_non_existent'
# Add a student to Certificate exception list
self.certificates_section.add_certificate_exception(invalid_user, '')
self.certificates_section.add_certificate_exception(self.user_name, '')

# Click 'Generate Exception Certificates' button
self.certificates_section.click_generate_certificate_exceptions_button()
self.certificates_section.wait_for_ajax()

# validate certificate exception synced with server is visible in certificate exceptions list
self.assertIn(
'Student (username/email={}) does not exist'.format(invalid_user),
'Certificate generation started for white listed students.',
self.certificates_section.message.text
)
23 changes: 22 additions & 1 deletion lms/djangoapps/certificates/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ class Meta(object):
notes = models.TextField(default=None, null=True)

@classmethod
def get_certificate_white_list(cls, course_id):
def get_certificate_white_list(cls, course_id, student=None):
"""
Return certificate white list for the given course as dict object,
returned dictionary will have the following key-value pairs
Expand All @@ -133,6 +133,8 @@ def get_certificate_white_list(cls, course_id):

"""
white_list = cls.objects.filter(course_id=course_id, whitelist=True)
if student:
white_list = white_list.filter(user=student)
result = []

for item in white_list:
Expand Down Expand Up @@ -214,6 +216,25 @@ def get_unique_statuses(cls, course_key=None, flat=False):
else:
return query.values('status').annotate(count=Count('status'))

def invalidate(self):
"""
Invalidate Generated Certificate by marking it 'unavailable'.

Following is the list of fields with their defaults
1 - verify_uuid = '',
2 - download_uuid = '',
3 - download_url = '',
4 - grade = ''
5 - status = 'unavailable'
"""
self.verify_uuid = ''
self.download_uuid = ''
self.download_url = ''
self.grade = ''
self.status = CertificateStatuses.unavailable

self.save()


@receiver(post_save, sender=GeneratedCertificate)
def handle_post_cert_generated(sender, instance, **kwargs): # pylint: disable=unused-argument
Expand Down
2 changes: 1 addition & 1 deletion lms/djangoapps/certificates/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class Meta(object):

course_id = None
whitelist = True
notes = None
notes = 'Test Notes'


class BadgeAssertionFactory(DjangoModelFactory):
Expand Down
Loading