Skip to content

Commit

Permalink
fix: 500 error message during opening program certificate
Browse files Browse the repository at this point in the history
Error 500 occurs when going to the program certificate page if
an organization is connected to the Authoring organizations
field with an empty field Certificate logo image.
  • Loading branch information
DmytroAlipov committed Nov 13, 2023
1 parent 5ba6912 commit 298bce7
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 2 deletions.
3 changes: 2 additions & 1 deletion course_discovery/apps/course_metadata/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
MarketingSiteAPIClientException, MarketingSitePublisherException
)
from course_discovery.apps.course_metadata.forms import (
CourseAdminForm, CourseRunAdminForm, PathwayAdminForm, ProgramAdminForm
CourseAdminForm, CourseRunAdminForm, OrganizationForm, PathwayAdminForm, ProgramAdminForm
)
from course_discovery.apps.course_metadata.models import * # pylint: disable=wildcard-import
from course_discovery.apps.course_metadata.views import (
Expand Down Expand Up @@ -598,6 +598,7 @@ class OrganizationUserRoleInline(admin.TabularInline):

@admin.register(Organization)
class OrganizationAdmin(admin.ModelAdmin):
form = OrganizationForm
list_display = ('uuid', 'key', 'name',)
inlines = [OrganizationUserRoleInline, ]
list_filter = ('partner',)
Expand Down
27 changes: 26 additions & 1 deletion course_discovery/apps/course_metadata/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.utils.translation import gettext_lazy as _

from course_discovery.apps.course_metadata.choices import ProgramStatus
from course_discovery.apps.course_metadata.models import Course, CourseRun, Pathway, Program
from course_discovery.apps.course_metadata.models import Course, CourseRun, Organization, Pathway, Program
from course_discovery.apps.course_metadata.widgets import SortedModelSelect2Multiple


Expand Down Expand Up @@ -68,6 +68,31 @@ def clean(self):

return self.cleaned_data

def clean_authoring_organizations(self):
authoring_organizations = self.cleaned_data.get('authoring_organizations')
orgs_with_empty_certificate_logo_image = []

for organization in authoring_organizations:
if not organization.certificate_logo_image:
orgs_with_empty_certificate_logo_image.append(organization.name)

if orgs_with_empty_certificate_logo_image:
error_message = f'Certificate logo image cannot be empty for organizations: ' \
f'{", ".join(orgs_with_empty_certificate_logo_image)}.'
raise ValidationError(error_message)

return authoring_organizations


class OrganizationForm(forms.ModelForm):
class Meta:
model = Organization
fields = '__all__'

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['certificate_logo_image'].required = True


class CourseRunSelectionForm(forms.ModelForm):
class Meta:
Expand Down
72 changes: 72 additions & 0 deletions course_discovery/apps/course_metadata/tests/test_forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from django.test import TestCase

from course_discovery.apps.api.tests.mixins import SiteMixin
from course_discovery.apps.core.tests.factories import USER_PASSWORD, UserFactory
from course_discovery.apps.course_metadata.choices import ProgramStatus
from course_discovery.apps.course_metadata.forms import ProgramAdminForm
from course_discovery.apps.course_metadata.tests import factories


class ProgramAdminFormTests(SiteMixin, TestCase):
""" Tests ProgramAdminForm. """

@classmethod
def setUpClass(cls):
super().setUpClass()
cls.user = UserFactory(is_staff=True, is_superuser=True)
cls.course_runs = factories.CourseRunFactory.create_batch(3)
cls.courses = [course_run.course for course_run in cls.course_runs]
cls.product_source = factories.SourceFactory()

cls.excluded_course_run = factories.CourseRunFactory(course=cls.courses[0])
cls.program = factories.ProgramFactory(
courses=cls.courses,
excluded_course_runs=[cls.excluded_course_run],
partner=cls.partner,
)
cls.org_1 = factories.OrganizationFactory(certificate_logo_image=None)
cls.org_2 = factories.OrganizationFactory(certificate_logo_image=None)
cls.org_3 = factories.OrganizationFactory()

def setUp(self):
super().setUp()
self.client.login(username=self.user.username, password=USER_PASSWORD)

def _post_data(self, status=ProgramStatus.Unpublished, marketing_slug='/foo'):
return {
'title': 'some test title',
'courses': [self.courses[0].id],
'type': self.program.type.id,
'status': status,
'marketing_slug': marketing_slug,
'partner': self.program.partner.id,
'product_source': self.product_source.id,
'authoring_organizations': [self.org_1.id, self.org_2.id, self.org_3.id],
}

def test_clean_authoring_organizations_with_empty_certificate_logo_image(self):
"""
Test verifies that the form is invalid if certificate_logo_image
is empty for any of the authoring_organizations.
"""
data = self._post_data()
form = ProgramAdminForm(data=data)
self.assertFalse(form.is_valid())
expected_error_message = f'Certificate logo image cannot be empty for organizations: ' \
f'{self.org_1.name}, {self.org_2.name}.'

self.assertEqual(form.errors['authoring_organizations'][0], expected_error_message)

def test_clean_authoring_organizations_with_non_empty_certificate_logo_image(self):
"""
Test verifies that the form is valid only if certificate_logo_image
is not empty for all authoring_organizations.
"""
self.org_1.certificate_logo_image = 'logo1.jpg'
self.org_1.save()
self.org_2.certificate_logo_image = 'logo2.jpg'
self.org_2.save()
data = self._post_data()
form = ProgramAdminForm(data=data)

self.assertTrue(form.is_valid())

0 comments on commit 298bce7

Please sign in to comment.