diff --git a/common/djangoapps/util/organizations_helpers.py b/common/djangoapps/util/organizations_helpers.py index 5164ae3dd9..124ab8f1c9 100644 --- a/common/djangoapps/util/organizations_helpers.py +++ b/common/djangoapps/util/organizations_helpers.py @@ -88,6 +88,16 @@ def get_course_organizations(course_id): return organizations_api.get_course_organizations(course_id) +def get_course_organization_id(course_id): + """ + Returns organization id for course or None if the course is not linked to an org + """ + course_organization = get_course_organizations(course_id) + if course_organization: + return course_organization[0]['id'] + return None + + def organizations_enabled(): """ Returns boolean indication if organizations app is enabled on not. diff --git a/lms/djangoapps/certificates/admin.py b/lms/djangoapps/certificates/admin.py index 378bf4c106..fc10ca0159 100644 --- a/lms/djangoapps/certificates/admin.py +++ b/lms/djangoapps/certificates/admin.py @@ -47,7 +47,7 @@ class CertificateTemplateAdmin(admin.ModelAdmin): """ Django admin customizations for CertificateTemplate model """ - list_display = ('name', 'description', 'organization_id', 'course_key', 'mode', 'is_active') + list_display = ('name', 'description', 'organization_id', 'course_key', 'mode', 'language', 'is_active') form = CertificateTemplateForm diff --git a/lms/djangoapps/certificates/api.py b/lms/djangoapps/certificates/api.py index 7ce8155a48..a2f710bbd6 100644 --- a/lms/djangoapps/certificates/api.py +++ b/lms/djangoapps/certificates/api.py @@ -8,6 +8,7 @@ import logging from django.conf import settings from django.core.urlresolvers import reverse +from django.db.models import Q from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey @@ -27,7 +28,7 @@ from certificates.queue import XQueueCertInterface from eventtracking import tracker from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.xmodule_django.models import CourseKeyField -from util.organizations_helpers import get_course_organizations +from util.organizations_helpers import get_course_organization_id from xmodule.modulestore.django import modulestore log = logging.getLogger("edx.certificate") @@ -463,49 +464,76 @@ def get_active_web_certificate(course, is_preview_mode=None): return None -def get_certificate_template(course_key, mode, language): # pylint: disable=unused-argument +def get_certificate_template(course_key, mode, language): """ Retrieves the custom certificate template based on course_key, mode, and language. """ - org_id, template = None, None + template = None # fetch organization of the course - course_organization = get_course_organizations(course_key) - if course_organization: - org_id = course_organization[0]['id'] + org_id = get_course_organization_id(course_key) - if org_id and mode: - template = CertificateTemplate.objects.filter( + # only consider active templates + active_templates = CertificateTemplate.objects.filter(is_active=True) + + if org_id and mode: # get template by org, mode, and key + org_mode_and_key_templates = active_templates.filter( organization_id=org_id, - course_key=course_key, mode=mode, - is_active=True + course_key=course_key ) - # if don't template find by org and mode - if not template and org_id and mode: - template = CertificateTemplate.objects.filter( + template = get_language_specific_template_or_default(language, org_mode_and_key_templates) + + # since no template matched that course_key, only consider templates with empty course_key + empty_course_key_templates = active_templates.filter(course_key=CourseKeyField.Empty) + if not template and org_id and mode: # get template by org and mode + org_and_mode_templates = empty_course_key_templates.filter( organization_id=org_id, - course_key=CourseKeyField.Empty, - mode=mode, - is_active=True + mode=mode ) - # if don't template find by only org - if not template and org_id: - template = CertificateTemplate.objects.filter( + template = get_language_specific_template_or_default(language, org_and_mode_templates) + if not template and org_id: # get template by only org + org_templates = empty_course_key_templates.filter( organization_id=org_id, - course_key=CourseKeyField.Empty, - mode=None, - is_active=True + mode=None ) - # if we still don't template find by only course mode - if not template and mode: - template = CertificateTemplate.objects.filter( + template = get_language_specific_template_or_default(language, org_templates) + if not template and mode: # get template by only mode + mode_templates = empty_course_key_templates.filter( organization_id=None, - course_key=CourseKeyField.Empty, - mode=mode, - is_active=True + mode=mode ) + template = get_language_specific_template_or_default(language, mode_templates) + #return template[0].template if template else None + return template.template if template else None - return template[0].template if template else None + +def get_language_specific_template_or_default(language, templates): + """ + Returns templates that match passed in language. + Returns default templates If no language matches, or language passed is None + """ + two_letter_language = _get_two_letter_language_code(language) + language_or_default_templates = list(templates.filter(Q(language=two_letter_language) | Q(language=None))) + language_specific_template = get_language_specific_template(language, language_or_default_templates) + if language_specific_template: + return language_specific_template + else: + return language_or_default_templates[0] if language_or_default_templates else None + + +def get_language_specific_template(language, templates): + for template in templates: + if template.language == language: + return template + return None + + +def _get_two_letter_language_code(language_code): + """ + Shortens language to only first two characters (e.g. es-419 becomes es) + This is needed because Catalog returns locale language which is not always a 2 letter code. + """ + return language_code[:2] if language_code else None def emit_certificate_event(event_name, user, course_id, course=None, event_data=None): diff --git a/lms/djangoapps/certificates/migrations/0011_certificatetemplate_alter_unique.py b/lms/djangoapps/certificates/migrations/0011_certificatetemplate_alter_unique.py new file mode 100644 index 0000000000..8ea49e8815 --- /dev/null +++ b/lms/djangoapps/certificates/migrations/0011_certificatetemplate_alter_unique.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +import logging +from django.db import migrations, models +from opaque_keys.edx.keys import CourseKey +from openedx.core.djangoapps.xmodule_django.models import CourseKeyField + +log = logging.getLogger(__name__) + +def revert_alter_unique(apps, schema_editor): + CertificateTemplateModel = apps.get_model("certificates", "CertificateTemplate") + + all_unique_templates_ignoring_language = CertificateTemplateModel.objects.values_list( + "organization_id", + "course_key", + "mode").distinct() + + for org_id, course_key, mode in all_unique_templates_ignoring_language: + key = CourseKey.from_string(course_key) if course_key else CourseKeyField.Empty + templates = CertificateTemplateModel.objects.filter(organization_id=org_id, course_key=key, mode=mode) + if templates.count() > 1: + # remove all templates past the first (null or default languages are ordered first) + language_specific_templates = templates.order_by('language')[1:] + language_specific_template_ids = language_specific_templates.values_list('id', flat=True) + for template in language_specific_templates: + log.info('Deleting template ' + str(template.id) + ' with details {' + + " name: "+ str(template.name) + + " description: "+ str(template.description) + + " template: "+ str(template.template) + + " organization_id: "+ str(template.organization_id) + + " course_key: "+ str(template.course_key) + + " mode: "+ str(template.mode) + + " is_active: "+ str(template.is_active) + + " language: "+ str(template.language) + " }" + ) + CertificateTemplateModel.objects.filter(id__in=list(language_specific_template_ids)).delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ('certificates', '0010_certificatetemplate_language'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='certificatetemplate', + unique_together=set([('organization_id', 'course_key', 'mode', 'language')]), + ), + migrations.RunPython(migrations.RunPython.noop, reverse_code=revert_alter_unique) + ] diff --git a/lms/djangoapps/certificates/models.py b/lms/djangoapps/certificates/models.py index 613fa69451..27c4313132 100644 --- a/lms/djangoapps/certificates/models.py +++ b/lms/djangoapps/certificates/models.py @@ -1063,7 +1063,7 @@ class CertificateTemplate(TimeStampedModel): class Meta(object): get_latest_by = 'created' - unique_together = (('organization_id', 'course_key', 'mode'),) + unique_together = (('organization_id', 'course_key', 'mode', 'language'),) app_label = "certificates" diff --git a/lms/djangoapps/certificates/signals.py b/lms/djangoapps/certificates/signals.py index faa2444b38..edce379a4c 100644 --- a/lms/djangoapps/certificates/signals.py +++ b/lms/djangoapps/certificates/signals.py @@ -7,7 +7,6 @@ from django.db.models.signals import post_save from django.dispatch import receiver from certificates.models import ( - CertificateGenerationCourseSetting, CertificateWhitelist, CertificateStatuses, GeneratedCertificate diff --git a/lms/djangoapps/certificates/tests/test_webview_views.py b/lms/djangoapps/certificates/tests/test_webview_views.py index 7e348d70d8..fadda9ce0a 100644 --- a/lms/djangoapps/certificates/tests/test_webview_views.py +++ b/lms/djangoapps/certificates/tests/test_webview_views.py @@ -18,6 +18,7 @@ from nose.plugins.attrib import attr from certificates.api import get_certificate_url from certificates.models import ( + CertificateGenerationCourseSetting, CertificateHtmlViewConfiguration, CertificateSocialNetworks, CertificateStatuses, @@ -147,7 +148,7 @@ class CommonCertificatesTestCase(ModuleStoreTestCase): self.course.save() self.store.update_item(self.course, self.user.id) - def _create_custom_template(self, org_id=None, mode=None, course_key=None): + def _create_custom_template(self, org_id=None, mode=None, course_key=None, language=None): """ Creates a custom certificate template entry in DB. """ @@ -170,7 +171,36 @@ class CommonCertificatesTestCase(ModuleStoreTestCase): organization_id=org_id, course_key=course_key, mode=mode, - is_active=True + is_active=True, + language=language + ) + template.save() + + def _create_custom_named_template(self, template_name, org_id=None, mode=None, course_key=None, language=None): + """ + Creates a custom certificate template entry in DB. + """ + template_html = """ + <%namespace name='static' file='static_content.html'/> + + + lang: ${LANGUAGE_CODE} + course name: """ + template_name + """ + mode: ${course_mode} + ${accomplishment_copy_course_description} + ${twitter_url} + + + + """ + template = CertificateTemplate( + name=template_name, + template=template_html, + organization_id=org_id, + course_key=course_key, + mode=mode, + is_active=True, + language=language ) template.save() @@ -882,94 +912,97 @@ class CertificatesViewsTests(CommonCertificatesTestCase): response_json = json.loads(response.content) self.assertEqual(CertificateStatuses.generating, response_json['add_status']) + #TEMPLATES WITHOUT LANGUAGE TESTS @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) @override_settings(LANGUAGE_CODE='fr') @patch('certificates.views.webview.get_course_run_details') - def test_certificate_custom_template_with_org_mode_course(self, mock_get_course_run_details): + def test_certificate_custom_template_with_org_mode_and_course_key(self, mock_get_course_run_details): """ Tests custom template search and rendering. This test should check template matching when org={org}, course={course}, mode={mode}. """ mock_get_course_run_details.return_value = {'content_language': 'en'} self._add_course_certificates(count=1, signatory_count=2) - self._create_custom_template(org_id=1, mode='honor', course_key=unicode(self.course.id)) - self._create_custom_template(org_id=2, mode='honor') + self._create_custom_named_template('test_template_1_course', org_id=1, mode='honor', course_key=unicode(self.course.id)) + self._create_custom_named_template('test_template_2_course', org_id=1, mode='verified', course_key=unicode(self.course.id)) + self._create_custom_named_template('test_template_3_course', org_id=2, mode='honor') test_url = get_certificate_url( user_id=self.user.id, course_id=unicode(self.course.id) ) - with patch('certificates.api.get_course_organizations') as mock_get_orgs: - mock_get_orgs.side_effect = [ - [{"id": 1, "name": "organization name"}], - [{"id": 2, "name": "organization name 2"}], - ] + with patch('certificates.api.get_course_organization_id') as mock_get_org_id: + mock_get_org_id.side_effect = [1, 2] response = self.client.get(test_url) self.assertEqual(response.status_code, 200) self.assertContains(response, 'lang: fr') - self.assertContains(response, 'course name: course_title_0') + self.assertContains(response, 'course name: test_template_1_course') # test with second organization template response = self.client.get(test_url) self.assertEqual(response.status_code, 200) self.assertContains(response, 'lang: fr') - self.assertContains(response, 'course name: course_title_0') + self.assertContains(response, 'course name: test_template_3_course') @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) @patch('certificates.views.webview.get_course_run_details') - def test_certificate_custom_template_with_org(self, mock_get_course_run_details): + def test_certificate_custom_template_with_org_and_mode(self, mock_get_course_run_details): """ - Tests custom template search if we have a single template for organization and mode - with course set to Null. + Tests custom template search if no template matches course_key, but a template does + match org and mode. This test should check template matching when org={org}, course=Null, mode={mode}. """ mock_get_course_run_details.return_value = {'content_language': 'en'} - course = CourseFactory.create( + othercourse = CourseFactory.create( org='cstX', number='cst_22', display_name='custom template course' ) self._add_course_certificates(count=1, signatory_count=2) - self._create_custom_template(org_id=1, mode='honor') - self._create_custom_template(org_id=1, mode='honor', course_key=course.id) + self._create_custom_named_template('test_template_1_course', org_id=1, mode='honor') # Correct template + self._create_custom_named_template( # wrong course key + 'test_template_2_course', + org_id=1, + mode='honor', + course_key=unicode(othercourse.id) + ) + self._create_custom_named_template('test_template_3_course', org_id=1, mode='verified') # wrong mode + self._create_custom_named_template('test_template_4_course', org_id=2, mode='honor') # wrong org test_url = get_certificate_url( user_id=self.user.id, course_id=unicode(self.course.id) ) - with patch('certificates.api.get_course_organizations') as mock_get_orgs: - mock_get_orgs.side_effect = [ - [{"id": 1, "name": "organization name"}], - ] + with patch('certificates.api.get_course_organization_id') as mock_get_org_id: + mock_get_org_id.side_effect = [1] response = self.client.get(test_url) self.assertEqual(response.status_code, 200) - self.assertContains(response, 'course name: course_title_0') + self.assertContains(response, 'course name: test_template_1_course') @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) @patch('certificates.views.webview.get_course_run_details') - def test_certificate_custom_template_with_organization(self, mock_get_course_run_details): + def test_certificate_custom_template_with_org(self, mock_get_course_run_details): """ Tests custom template search when we have a single template for a organization. This test should check template matching when org={org}, course=Null, mode=null. """ mock_get_course_run_details.return_value = {'content_language': 'en'} self._add_course_certificates(count=1, signatory_count=2) - self._create_custom_template(org_id=1, mode='honor') - self._create_custom_template(org_id=1, mode='honor', course_key=self.course.id) - self._create_custom_template(org_id=2) + self._create_custom_named_template('test_template_1_course', org_id=1, mode=None) # Correct template + self._create_custom_named_template('test_template_2_course', org_id=1, mode='verified') # wrong mode + self._create_custom_named_template('test_template_3_course', org_id=2, mode=None) # wrong org test_url = get_certificate_url( user_id=self.user.id, course_id=unicode(self.course.id) ) - with patch('certificates.api.get_course_organizations') as mock_get_orgs: - mock_get_orgs.side_effect = [ - [{"id": 2, "name": "organization name 2"}], - ] + with patch('certificates.api.get_course_organization_id') as mock_get_org_id: + mock_get_org_id.side_effect = [1] response = self.client.get(test_url) self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_template_1_course') @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) @patch('certificates.views.webview.get_course_run_details') - def test_certificate_custom_template_with_course_mode(self, mock_get_course_run_details): + def test_certificate_custom_template_with_mode(self, mock_get_course_run_details): """ Tests custom template search if we have a single template for a course mode. This test should check template matching when org=null, course=Null, mode={mode}. @@ -977,17 +1010,231 @@ class CertificatesViewsTests(CommonCertificatesTestCase): mock_get_course_run_details.return_value = {'content_language': 'en'} mode = 'honor' self._add_course_certificates(count=1, signatory_count=2) - self._create_custom_template(mode=mode) + self._create_custom_named_template('test_template_1_course', org_id=None, mode=mode) # Correct template + self._create_custom_named_template('test_template_2_course', org_id=None, mode='verified') # wrong mode + self._create_custom_named_template('test_template_3_course', org_id=2, mode=mode) # wrong org test_url = get_certificate_url( user_id=self.user.id, course_id=unicode(self.course.id) ) - with patch('certificates.api.get_course_organizations') as mock_get_orgs: - mock_get_orgs.return_value = [] + with patch('certificates.api.get_course_organization_id') as mock_get_org_id: + mock_get_org_id.return_value = None response = self.client.get(test_url) self.assertEqual(response.status_code, 200) self.assertContains(response, 'mode: {}'.format(mode)) + self.assertContains(response, 'course name: test_template_1_course') + + ## Templates With Language tests + #1 + @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) + @override_settings(LANGUAGE_CODE='fr') + @patch('certificates.views.webview.get_course_run_details') + @patch('certificates.api.get_course_organization_id') + def test_certificate_custom_language_template_with_org_mode_and_course_key(self, mock_get_org_id, mock_get_course_run_details): + """ + Tests custom template search and rendering. + This test should check template matching when org={org}, course={course}, mode={mode}. + """ + right_language = 'es' + wrong_language = 'fr' + mock_get_org_id.return_value = 1 + mock_get_course_run_details.return_value = {'content_language': 'es'} + CertificateGenerationCourseSetting.set_language_specific_templates_enabled_for_course(self.course.id, True) + + self._add_course_certificates(count=1, signatory_count=2) + + test_url = get_certificate_url( + user_id=self.user.id, + course_id=unicode(self.course.id) + ) + #create a org_mode_and_coursekey template language=null + self._create_custom_named_template('test_null_lang_template', org_id=1, mode='honor', course_key=unicode(self.course.id), language=None) + #verify return template lang = null + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a org_mode_and_coursekey template language=wrong_language + self._create_custom_named_template('test_wrong_lang_template', org_id=1, mode='honor', course_key=unicode(self.course.id), language=wrong_language) + #verify returns null lang template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a org_mode_and_coursekey template language=lang + self._create_custom_named_template('test_right_lang_template', org_id=1, mode='honor', course_key=unicode(self.course.id), language=right_language) + # verify return right_language template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_right_lang_template') + + #2 + @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) + @patch('certificates.views.webview.get_course_run_details') + @patch('certificates.api.get_course_organization_id') + def test_certificate_custom_language_template_with_org_and_mode(self, mock_get_org_id, mock_get_course_run_details): + """ + Tests custom template search if no template matches course_key, but a template does + match org and mode. + This test should check template matching when org={org}, course=Null, mode={mode}. + """ + right_language = 'es' + wrong_language = 'fr' + mock_get_org_id.return_value = 1 + mock_get_course_run_details.return_value = {'content_language': 'es'} + CertificateGenerationCourseSetting.set_language_specific_templates_enabled_for_course(self.course.id, True) + + self._add_course_certificates(count=1, signatory_count=2) + + test_url = get_certificate_url( + user_id=self.user.id, + course_id=unicode(self.course.id) + ) + #create a org and mode template language=null + self._create_custom_named_template('test_null_lang_template', org_id=1, mode='honor', language=None) + #verify return template lang = null + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a org and mode template language=wrong_language + self._create_custom_named_template('test_wrong_lang_template', org_id=1, mode='honor', language=wrong_language) + #verify returns null lang template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a org and mode template language=lang + self._create_custom_named_template('test_right_lang_template', org_id=1, mode='honor', language=right_language) + # verify return right_language template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_right_lang_template') + + #3 + @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) + @patch('certificates.views.webview.get_course_run_details') + @patch('certificates.api.get_course_organization_id') + def test_certificate_custom_language_template_with_org(self, mock_get_org_id, mock_get_course_run_details): + """ + Tests custom template search when we have a single template for a organization. + This test should check template matching when org={org}, course=Null, mode=null. + """ + right_language = 'es' + wrong_language = 'fr' + mock_get_org_id.return_value = 1 + mock_get_course_run_details.return_value = {'content_language': 'es'} + CertificateGenerationCourseSetting.set_language_specific_templates_enabled_for_course(self.course.id, True) + + self._add_course_certificates(count=1, signatory_count=2) + test_url = get_certificate_url( + user_id=self.user.id, + course_id=unicode(self.course.id) + ) + #create a org template language=null + self._create_custom_named_template('test_null_lang_template', org_id=1, language=None) + #verify return template lang = null + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a org template language=wrong_language + self._create_custom_named_template('test_wrong_lang_template', org_id=1, language=wrong_language) + #verify returns null lang template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a org template language=lang + self._create_custom_named_template('test_right_lang_template', org_id=1, language=right_language) + # verify return right_language template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_right_lang_template') + + #4 + @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) + @patch('certificates.views.webview.get_course_run_details') + @patch('certificates.api.get_course_organization_id') + def test_certificate_custom_language_template_with_mode(self, mock_get_org_id, mock_get_course_run_details): + """ + Tests custom template search if we have a single template for a course mode. + This test should check template matching when org=null, course=Null, mode={mode}. + """ + right_language = 'es' + wrong_language = 'fr' + mock_get_org_id.return_value = 1 + mock_get_course_run_details.return_value = {'content_language': 'es'} + CertificateGenerationCourseSetting.set_language_specific_templates_enabled_for_course(self.course.id, True) + + self._add_course_certificates(count=1, signatory_count=2) + + test_url = get_certificate_url( + user_id=self.user.id, + course_id=unicode(self.course.id) + ) + #create a mode template language=null + self._create_custom_named_template('test_null_lang_template', mode='honor', language=None) + #verify return template with lang = null + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a mode template language=wrong_language + self._create_custom_named_template('test_wrong_lang_template', mode='honor', language=wrong_language) + #verify returns null lang template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a mode template language=lang + self._create_custom_named_template('test_right_lang_template', mode='honor', language=right_language) + # verify return right_language template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_right_lang_template') + + @override_settings(FEATURES=FEATURES_WITH_CUSTOM_CERTS_ENABLED) + @patch('certificates.views.webview.get_course_run_details') + @patch('certificates.api.get_course_organization_id') + def test_certificate_custom_language_template_with_locale_language_from_catalogue(self, mock_get_org_id, mock_get_course_run_details): + """ + Tests custom template search if we have a single template for a course mode. + This test should check template matching when org=null, course=Null, mode={mode}. + """ + right_language = 'es' + wrong_language = 'fr' + mock_get_org_id.return_value = 1 + mock_get_course_run_details.return_value = {'content_language': 'es-419'} + CertificateGenerationCourseSetting.set_language_specific_templates_enabled_for_course(self.course.id, True) + + self._add_course_certificates(count=1, signatory_count=2) + + test_url = get_certificate_url( + user_id=self.user.id, + course_id=unicode(self.course.id) + ) + #create a mode template language=null + self._create_custom_named_template('test_null_lang_template', org_id=1, mode='honor', language=None) + #verify return template with lang = null + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a mode template language=wrong_language + self._create_custom_named_template('test_wrong_lang_template', org_id=1, mode='honor', language=wrong_language) + #verify returns null lang template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_null_lang_template') + + #create a mode template language=lang + self._create_custom_named_template('test_right_lang_template', org_id=1, mode='honor', language=right_language) + # verify return right_language template + response = self.client.get(test_url) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'course name: test_right_lang_template') @ddt.data(True, False) @patch('certificates.views.webview.get_course_run_details') @@ -1013,8 +1260,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase): }): with patch('django.http.HttpRequest.build_absolute_uri') as mock_abs_uri: mock_abs_uri.return_value = '='.join(['http://localhost/?param', u'é']) - with patch('certificates.api.get_course_organizations') as mock_get_orgs: - mock_get_orgs.return_value = [] + with patch('certificates.api.get_course_organization_id') as mock_get_org_id: + mock_get_org_id.return_value = None response = self.client.get(test_url) self.assertEqual(response.status_code, 200) if custom_certs_enabled: @@ -1038,8 +1285,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase): ) # render certificate without template asset - with patch('certificates.api.get_course_organizations') as mock_get_orgs: - mock_get_orgs.return_value = [] + with patch('certificates.api.get_course_organization_id') as mock_get_org_id: + mock_get_org_id.return_value = None response = self.client.get(test_url) self.assertContains(response, '') @@ -1051,8 +1298,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase): template_asset.save() # render certificate with template asset - with patch('certificates.api.get_course_organizations') as mock_get_orgs: - mock_get_orgs.return_value = [] + with patch('certificates.api.get_course_organization_id') as mock_get_org_id: + mock_get_org_id.return_value = None response = self.client.get(test_url) self.assertContains( response, ''.format(