Skip to content

Commit

Permalink
fix: configure course or program format (#2747)
Browse files Browse the repository at this point in the history
  • Loading branch information
shahbaz-shabbir05 authored Oct 18, 2023
1 parent 8d14fd9 commit 61b350a
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 13 deletions.
3 changes: 3 additions & 0 deletions cms/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,6 @@
WEBINAR_HEADER_BANNER = "images/webinars/webinar-header-banner.jpg"
UPCOMING_WEBINAR_BUTTON_TITLE = "REGISTER"
ON_DEMAND_WEBINAR_BUTTON_TITLE = "VIEW RECORDING"

FORMAT_ONLINE = "Online"
FORMAT_OTHER = "Other"
53 changes: 53 additions & 0 deletions cms/migrations/0064_productpage_format_field.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Generated by Django 3.2.21 on 2023-09-13 12:11

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("cms", "0063_webinarindexpage_banner_image"),
]

operations = [
migrations.AddField(
model_name="coursepage",
name="format",
field=models.CharField(
choices=[("Online", "Online"), ("Other", "Other")],
default="Online",
help_text="A short description indicating the format of a program or course",
max_length=20,
),
),
migrations.AddField(
model_name="externalcoursepage",
name="format",
field=models.CharField(
choices=[("Online", "Online"), ("Other", "Other")],
default="Online",
help_text="A short description indicating the format of a program or course",
max_length=20,
),
),
migrations.AddField(
model_name="externalprogrampage",
name="format",
field=models.CharField(
choices=[("Online", "Online"), ("Other", "Other")],
default="Online",
help_text="A short description indicating the format of a program or course",
max_length=20,
),
),
migrations.AddField(
model_name="programpage",
name="format",
field=models.CharField(
choices=[("Online", "Online"), ("Other", "Other")],
default="Online",
help_text="A short description indicating the format of a program or course",
max_length=20,
),
),
]
13 changes: 13 additions & 0 deletions cms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
WEBINAR_DEFAULT_IMAGES,
WEBINAR_HEADER_BANNER,
WEBINAR_INDEX_SLUG,
FORMAT_ONLINE,
FORMAT_OTHER,
)
from cms.forms import CertificatePageForm
from courses.constants import DEFAULT_COURSE_IMG_PATH, PROGRAM_RUN_ID_PATTERN
Expand Down Expand Up @@ -787,6 +789,16 @@ class Meta:
blank=True,
help_text="A short description indicating how long it takes to complete (e.g. '4 weeks')",
)
FORMAT_CHOICES = [
(FORMAT_ONLINE, FORMAT_ONLINE),
(FORMAT_OTHER, FORMAT_OTHER),
]
format = models.CharField(
max_length=20,
choices=FORMAT_CHOICES,
default=FORMAT_ONLINE,
help_text="A short description indicating the format of a program or course",
)
background_image = models.ForeignKey(
Image,
null=True,
Expand Down Expand Up @@ -835,6 +847,7 @@ class Meta:
FieldPanel("video_title"),
FieldPanel("video_url"),
FieldPanel("duration"),
FieldPanel("format"),
FieldPanel("time_commitment"),
FieldPanel("description", classname="full"),
FieldPanel("catalog_details", classname="full"),
Expand Down
64 changes: 64 additions & 0 deletions cms/models_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
UPCOMING_WEBINAR,
UPCOMING_WEBINAR_BUTTON_TITLE,
WEBINAR_HEADER_BANNER,
FORMAT_ONLINE,
FORMAT_OTHER,
)
from cms.factories import (
CertificatePageFactory,
Expand Down Expand Up @@ -827,6 +829,7 @@ def test_course_page_properties():
description="<p>desc</p>",
catalog_details="<p>catalog desc</p>",
duration="1 week",
format=FORMAT_ONLINE,
video_title="<p>title</p>",
video_url="http://test.com/mock.mp4",
background_image__title="background-image",
Expand All @@ -836,6 +839,7 @@ def test_course_page_properties():
assert course_page.description == "<p>desc</p>"
assert course_page.catalog_details == "<p>catalog desc</p>"
assert course_page.duration == "1 week"
assert course_page.format == FORMAT_ONLINE
assert course_page.video_title == "<p>title</p>"
assert course_page.video_url == "http://test.com/mock.mp4"
assert course_page.background_image.title == "background-image"
Expand All @@ -851,6 +855,7 @@ def test_external_course_page_properties():
description="<p>desc</p>",
catalog_details="<p>catalog desc</p>",
duration="1 week",
format=FORMAT_OTHER,
video_title="<p>title</p>",
video_url="http://test.com/mock.mp4",
background_image__title="background-image",
Expand All @@ -861,6 +866,7 @@ def test_external_course_page_properties():
assert external_course_page.description == "<p>desc</p>"
assert external_course_page.catalog_details == "<p>catalog desc</p>"
assert external_course_page.duration == "1 week"
assert external_course_page.format == FORMAT_OTHER
assert external_course_page.video_title == "<p>title</p>"
assert external_course_page.video_url == "http://test.com/mock.mp4"
assert external_course_page.background_image.title == "background-image"
Expand All @@ -870,6 +876,33 @@ def test_external_course_page_properties():
assert external_course_page.product == external_course_page.course


def test_course_page_format_field_default_value():
"""
Verifies that the "format" field in a course page has the default value FORMAT_ONLINE.
"""
course_page = CoursePageFactory.create()

assert course_page.format == FORMAT_ONLINE


@pytest.mark.parametrize("course_format", [FORMAT_ONLINE, FORMAT_OTHER])
def test_course_page_format_field_choices(course_format, staff_user):
"""
Verifies that if the "format" field in a course page contains the values FORMAT_ONLINE and FORMAT_OTHER,
and they are in the same context.
"""
course_page = CoursePageFactory.create(format=course_format)

rf = RequestFactory()
request = rf.get("/")
request.user = staff_user

context = course_page.get_context(request=request)
context_format = context.get("page").format

assert context_format == course_format


def test_program_page_properties():
"""
Wagtail-page-related properties should return expected values if the Wagtail page exists
Expand All @@ -880,6 +913,7 @@ def test_program_page_properties():
description="<p>desc</p>",
catalog_details="<p>catalog desc</p>",
duration="1 week",
format=FORMAT_ONLINE,
video_title="<p>title</p>",
video_url="http://test.com/mock.mp4",
background_image__title="background-image",
Expand All @@ -889,6 +923,7 @@ def test_program_page_properties():
assert program_page.description == "<p>desc</p>"
assert program_page.catalog_details == "<p>catalog desc</p>"
assert program_page.duration == "1 week"
assert program_page.format == FORMAT_ONLINE
assert program_page.video_title == "<p>title</p>"
assert program_page.video_url == "http://test.com/mock.mp4"
assert program_page.background_image.title == "background-image"
Expand All @@ -904,6 +939,7 @@ def test_external_program_page_properties():
description="<p>desc</p>",
catalog_details="<p>catalog desc</p>",
duration="1 week",
format=FORMAT_OTHER,
video_title="<p>title</p>",
video_url="http://test.com/mock.mp4",
background_image__title="background-image",
Expand All @@ -914,11 +950,39 @@ def test_external_program_page_properties():
assert external_program_page.description == "<p>desc</p>"
assert external_program_page.catalog_details == "<p>catalog desc</p>"
assert external_program_page.duration == "1 week"
assert external_program_page.format == FORMAT_OTHER
assert external_program_page.video_title == "<p>title</p>"
assert external_program_page.video_url == "http://test.com/mock.mp4"
assert external_program_page.background_image.title == "background-image"


def test_program_page_format_field_default_value():
"""
Verifies that the "format" field in a program page has the default value FORMAT_ONLINE.
"""
program_page = ProgramPageFactory.create()

assert program_page.format == FORMAT_ONLINE


@pytest.mark.parametrize("program_format", [FORMAT_ONLINE, FORMAT_OTHER])
def test_program_page_format_field_choices(program_format, staff_user):
"""
Verifies that if the "format" field in a program page contains the values FORMAT_ONLINE and FORMAT_OTHER,
and they are in the same context.
"""
program_page = ProgramPageFactory.create(format=program_format)

rf = RequestFactory()
request = rf.get("/")
request.user = staff_user

context = program_page.get_context(request=request)
context_format = context.get("page").format

assert context_format == program_format


def test_course_page_learning_outcomes():
"""
CoursePage related LearningOutcomesPage should return expected values if it exists
Expand Down
3 changes: 1 addition & 2 deletions cms/templates/partials/metadata-tiles.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,8 @@
{% endif %}
<li>
<span class="title">FORMAT</span>
<span class="text">Online</span>
<span class="text">{{ page.format }}</span>
</li>

{% if page.product.current_price %}
<li>
<span class="title">PRICE</span>
Expand Down
10 changes: 3 additions & 7 deletions courses/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,7 @@ def get_credits(self, instance):

def get_format(self, instance): # pylint: disable=unused-argument
"""Returns the format of the course"""
# Currently hardcoded at the frontend as well, At some point we'll need to move it into CMS to make it
# configurable.
return "Online"
return instance.page.format if instance.page and instance.page.format else None

def get_platform(self, instance):
"""Returns the platform name of the course"""
Expand Down Expand Up @@ -374,10 +372,8 @@ def get_credits(self, instance):
)

def get_format(self, instance): # pylint: disable=unused-argument
"""Returns the format of the course"""
# Currently hardcoded at the frontend as well, At some point we'll need to move it into CMS to make it
# configurable.
return "Online"
"""Returns the format of the program"""
return instance.page.format if instance.page and instance.page.format else None

def get_platform(self, instance):
"""Returns the platform name of the program"""
Expand Down
12 changes: 9 additions & 3 deletions courses/serializers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from django.contrib.auth.models import AnonymousUser

from cms.factories import FacultyMembersPageFactory
from cms.constants import FORMAT_ONLINE, FORMAT_OTHER
from courses.factories import (
CourseFactory,
CourseRunEnrollmentFactory,
Expand All @@ -34,7 +35,6 @@
from ecommerce.serializers_test import datetime_format
from mitxpro.test_utils import assert_drf_json_equal, drf_datetime


pytestmark = [pytest.mark.django_db]


Expand All @@ -53,6 +53,7 @@ def test_base_program_serializer():

@pytest.mark.parametrize("has_product", [True, False])
@pytest.mark.parametrize("is_external", [True, False])
@pytest.mark.parametrize("program_format", [FORMAT_ONLINE, FORMAT_OTHER])
@pytest.mark.parametrize(
"duration, time_commitment, video_url, ceus, external_marketing_url",
[
Expand All @@ -76,6 +77,7 @@ def test_serialize_program(
mock_context,
has_product,
is_external,
program_format,
duration,
time_commitment,
video_url,
Expand All @@ -88,6 +90,7 @@ def test_serialize_program(
is_external=is_external,
page__certificate_page__CEUs=ceus,
page__duration=duration,
page__format=program_format,
page__time_commitment=time_commitment,
page__video_url=video_url,
page__external_marketing_url=external_marketing_url,
Expand Down Expand Up @@ -147,9 +150,9 @@ def test_serialize_program(
"topics": [{"name": topic.name} for topic in topics],
"time_commitment": time_commitment,
"duration": duration,
"format": program_format,
"video_url": video_url,
"credits": ceus,
"format": "Online",
"is_external": is_external,
"external_marketing_url": external_marketing_url,
"platform": program.platform.name,
Expand All @@ -174,6 +177,7 @@ def test_base_course_serializer():
@pytest.mark.parametrize("all_runs", [True, False])
@pytest.mark.parametrize("is_external", [True, False])
@pytest.mark.parametrize("course_page", [True, False])
@pytest.mark.parametrize("course_format", [FORMAT_ONLINE, FORMAT_OTHER])
@pytest.mark.parametrize(
"duration, time_commitment, video_url, ceus, external_marketing_url",
[
Expand All @@ -199,6 +203,7 @@ def test_serialize_course(
all_runs,
is_external,
course_page,
course_format,
duration,
time_commitment,
video_url,
Expand All @@ -219,6 +224,7 @@ def test_serialize_course(
is_external=is_external,
page__time_commitment=time_commitment,
page__duration=duration,
page__format=course_format,
page__video_url=video_url,
page__certificate_page__CEUs=ceus,
page__external_marketing_url=external_marketing_url,
Expand Down Expand Up @@ -275,9 +281,9 @@ def test_serialize_course(
"topics": [{"name": topic}] if course_page else [],
"time_commitment": time_commitment if course_page else None,
"duration": duration if course_page else None,
"format": course_format if course_page else None,
"video_url": video_url if course_page else None,
"credits": ceus if course_page else None,
"format": "Online",
"is_external": is_external,
"external_marketing_url": external_marketing_url if course_page else None,
"platform": course.platform.name,
Expand Down
Loading

0 comments on commit 61b350a

Please sign in to comment.