Skip to content

🐛(backend) skip hidden course runs from state calculation #2561

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).

### Fixed

- Skip hidden course runs from state calculation
- Fix frontend translation of Enroll now for external LMS backend

## [2.33.0] - 2024-12-02
Expand Down
2 changes: 1 addition & 1 deletion src/richie/apps/courses/models/course.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ def state(self):

for course_run in self.course_runs.only(
"start", "end", "enrollment_start", "enrollment_end"
):
).exclude(catalog_visibility=CourseRunCatalogVisibility.HIDDEN):
state = course_run.state
best_state = min(state, best_state)
if state["priority"] == CourseState.ONGOING_OPEN:
Expand Down
28 changes: 28 additions & 0 deletions tests/apps/courses/test_models_course_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

from richie.apps.courses.factories import CourseFactory, CourseRunFactory
from richie.apps.courses.models import CourseState
from richie.apps.courses.models.course import CourseRunCatalogVisibility


class CourseRunModelsTestCase(TestCase):
Expand Down Expand Up @@ -206,3 +207,30 @@ def test_models_course_state_ongoing_open(self):
with self.assertNumQueries(1):
state = course.state
self.assertEqual(state, expected_state)

def test_models_course_state_does_not_compute_hidden_runs(self):
"""
Confirm that course state should never be computed across course runs
having `catalog_visibility` as `hidden`.
"""
course = CourseFactory(should_publish=True)
on_going_course_run = self.create_run_ongoing_open(course)
future_open_course_run = self.create_run_future_open(course)

self.assertEqual(course.state["priority"], 0)

on_going_course_run.catalog_visibility = CourseRunCatalogVisibility.HIDDEN
on_going_course_run.save()

course.refresh_from_db()
on_going_course_run.refresh_from_db()

self.assertEqual(course.state["priority"], 1)

future_open_course_run.catalog_visibility = CourseRunCatalogVisibility.HIDDEN
future_open_course_run.save()

course.refresh_from_db()
future_open_course_run.refresh_from_db()

self.assertEqual(course.state["priority"], 7)
46 changes: 46 additions & 0 deletions tests/apps/courses/test_templates_category_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
End-to-end tests for the category detail view
"""

import datetime
import re
from unittest import mock

Expand All @@ -18,9 +19,11 @@
BlogPostFactory,
CategoryFactory,
CourseFactory,
CourseRunFactory,
OrganizationFactory,
PersonFactory,
)
from richie.apps.courses.models.course import CourseRun, CourseRunCatalogVisibility
from richie.plugins.nesteditem.defaults import ACCORDION


Expand Down Expand Up @@ -715,3 +718,46 @@ def test_template_category_detail_additional_info_page_id(self):

self.assertEqual(response.status_code, 200)
self.assertNotContains(response, message)

def test_templates_category_detail_cms_published_hidden_courses(self):
"""
Ensures that changing the course run `catalog_visibility` to `hidden`
parameter will prevent it from being take in account to compute the
course state on the category detail page
"""
category = CategoryFactory(should_publish=True)
course = CourseFactory.create(fill_categories=[category], should_publish=True)
CourseRunFactory.create(
direct_course=course,
catalog_visibility=CourseRunCatalogVisibility.COURSE_AND_SEARCH,
start=datetime.datetime.now(),
end=datetime.datetime.now() + datetime.timedelta(days=5),
enrollment_start=datetime.datetime.now() - datetime.timedelta(days=2),
enrollment_end=datetime.datetime.now() - datetime.timedelta(days=1),
)

course.refresh_from_db()
add_plugin(
course.extended_object.placeholders.get(slot="course_categories"),
CategoryPlugin,
"en",
page=category.extended_object,
)

courses_query = category.get_courses()

self.assertEqual(courses_query.count(), 1)
self.assertEqual(course.state["priority"], 5)
self.assertEqual(course.state["text"], "on-going")

course_runs = CourseRun.objects.filter(direct_course=course)
self.assertEqual(len(course_runs), 1)

course_runs[0].catalog_visibility = CourseRunCatalogVisibility.HIDDEN
course_runs[0].save()

courses_query = category.get_courses()

self.assertEqual(courses_query.count(), 1)
self.assertEqual(course.state["priority"], 7)
self.assertEqual(course.state["text"], "to be scheduled")
48 changes: 48 additions & 0 deletions tests/apps/courses/test_templates_organization_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
End-to-end tests for the organization detail view
"""

import datetime
import re
from unittest import mock

Expand All @@ -16,9 +17,11 @@
from richie.apps.courses.factories import (
CategoryFactory,
CourseFactory,
CourseRunFactory,
OrganizationFactory,
PersonFactory,
)
from richie.apps.courses.models.course import CourseRun, CourseRunCatalogVisibility


class OrganizationCMSTestCase(CMSTestCase):
Expand Down Expand Up @@ -698,3 +701,48 @@ def test_templates_organization_detail_with_related_organizations(self):
section = html.cssselect(".organization-detail__organizations")[0]
organization_glimpse = section.cssselect(".section__items--organizations > *")
self.assertEqual(len(organization_glimpse), 2)

def test_templates_organization_detail_cms_published_hidden_courses(self):
"""
Ensures that changing the course run `catalog_visibility` to `hidden`
parameter will prevent it from being take in account to compute the
course state on the organization detail page
"""
organization = OrganizationFactory(should_publish=True)
course = CourseFactory.create(
fill_organizations=[organization], should_publish=True
)
CourseRunFactory.create(
direct_course=course,
catalog_visibility=CourseRunCatalogVisibility.COURSE_AND_SEARCH,
start=datetime.datetime.now(),
end=datetime.datetime.now() + datetime.timedelta(days=5),
enrollment_start=datetime.datetime.now() - datetime.timedelta(days=2),
enrollment_end=datetime.datetime.now() - datetime.timedelta(days=1),
)

course.refresh_from_db()
add_plugin(
course.extended_object.placeholders.get(slot="course_organizations"),
OrganizationPlugin,
"en",
page=organization.extended_object,
)

courses_query = organization.get_courses()

self.assertEqual(courses_query.count(), 1)
self.assertEqual(course.state["priority"], 5)
self.assertEqual(course.state["text"], "on-going")

course_runs = CourseRun.objects.filter(direct_course=course)
self.assertEqual(len(course_runs), 1)

course_runs[0].catalog_visibility = CourseRunCatalogVisibility.HIDDEN
course_runs[0].save()

courses_query = organization.get_courses()

self.assertEqual(courses_query.count(), 1)
self.assertEqual(course.state["priority"], 7)
self.assertEqual(course.state["text"], "to be scheduled")
46 changes: 46 additions & 0 deletions tests/apps/courses/test_templates_person_detail.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
End-to-end tests for the person detail view
"""

import datetime
import re
from unittest import mock

Expand All @@ -22,9 +23,11 @@
BlogPostFactory,
CategoryFactory,
CourseFactory,
CourseRunFactory,
OrganizationFactory,
PersonFactory,
)
from richie.apps.courses.models.course import CourseRun, CourseRunCatalogVisibility


class PersonCMSTestCase(CMSTestCase):
Expand Down Expand Up @@ -661,3 +664,46 @@ def test_templates_person_detail_meta_description_empty(self):
response,
'<meta name="description"',
)

def test_templates_person_detail_cms_published_hidden_courses(self):
"""
Ensures that changing the course run `catalog_visibility` to `hidden`
parameter will prevent it from being take in account to compute the
course state on the person detail page
"""
person = PersonFactory(should_publish=True)
course = CourseFactory.create(fill_team=[person], should_publish=True)
CourseRunFactory.create(
direct_course=course,
catalog_visibility=CourseRunCatalogVisibility.COURSE_AND_SEARCH,
start=datetime.datetime.now(),
end=datetime.datetime.now() + datetime.timedelta(days=5),
enrollment_start=datetime.datetime.now() - datetime.timedelta(days=2),
enrollment_end=datetime.datetime.now() - datetime.timedelta(days=1),
)

course.refresh_from_db()
add_plugin(
course.extended_object.placeholders.get(slot="course_team"),
PersonPlugin,
"en",
page=person.extended_object,
)

courses_query = person.get_courses()

self.assertEqual(courses_query.count(), 1)
self.assertEqual(course.state["priority"], 5)
self.assertEqual(course.state["text"], "on-going")

course_runs = CourseRun.objects.filter(direct_course=course)
self.assertEqual(len(course_runs), 1)

course_runs[0].catalog_visibility = CourseRunCatalogVisibility.HIDDEN
course_runs[0].save()

courses_query = person.get_courses()

self.assertEqual(courses_query.count(), 1)
self.assertEqual(course.state["priority"], 7)
self.assertEqual(course.state["text"], "to be scheduled")