Skip to content

Commit

Permalink
🐛(courses) hide unpublished objects from list views (#1580)
Browse files Browse the repository at this point in the history
The template code was a bit too naïve and did not exclude
unpublished objects on the public site.
  • Loading branch information
sampaccoud authored Feb 4, 2022
1 parent cf53719 commit b3c46a8
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).

### Fixed

- Hide unpublished objects from list views (category, person and program)
- Add missing translation within search autocomplete menu
- Fix a layout issue on autosuggest search menu
- Fixed a layout issue on course glimpse
Expand Down
29 changes: 20 additions & 9 deletions src/richie/apps/courses/templates/courses/cms/category_list.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% extends "richie/fullwidth.html" %}
{% load cms_tags i18n %}
{% load cms_tags i18n pagination_tags %}

{% block subheader_content %}
<div class="subheader__container">
Expand All @@ -11,15 +11,26 @@ <h1 class="subheader__title">{{ current_page.get_title }}</h1>
{% block content %}
<div class="category-list">
<div class="category-glimpse-list">
{% for page in current_page.get_child_pages %}
{% if page.category %}
{% include "courses/cms/fragment_category_glimpse.html" with category=page.category category_variant="glimpse" %}
{% if current_page.publisher_is_draft %}
{% autopaginate current_page.get_child_pages 100 as object_list %}
{% else %}
{% autopaginate current_page.get_child_pages.published.distinct 100 as object_list %}
{% endif %}
{% empty %}
<p class="category-glimpse-list category-glimpse-list--empty">
{% trans "No categories" %}
</p>
{% endfor %}

{% for page in object_list %}
{% if page.category %}
{% include "courses/cms/fragment_category_glimpse.html" with category=page.category category_variant="glimpse" %}
{% endif %}
{% empty %}
<p class="category-glimpse-list category-glimpse-list--empty">
{% trans "No categories" %}
</p>
{% endfor %}

{% if object_list %}
{% paginate using "richie/pagination.html" %}
{% endif %}

</div>
</div>
{% endblock content %}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ <h1 class="subheader__title">{{ current_page.get_title }}</h1>
{% empty %}
<p class="organization-list__empty">{% trans "No organization yet" %}</p>
{% endfor %}

{% if object_list %}
{% paginate using "richie/pagination.html" %}
{% endif %}
</div>
</div>
{% endblock content %}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ <h1 class="subheader__title">{{ current_page.get_title }}</h1>

{% block content %}
<div class="person-list">
{% autopaginate current_page.get_child_pages 24 as object_list %}
{% if current_page.publisher_is_draft %}
{% autopaginate current_page.get_child_pages 100 as object_list %}
{% else %}
{% autopaginate current_page.get_child_pages.published.distinct 100 as object_list %}
{% endif %}

{% for page in object_list %}
{% if page.person %}
{% include "courses/cms/fragment_person_glimpse.html" with person=page.person %}
Expand Down
14 changes: 12 additions & 2 deletions src/richie/apps/courses/templates/courses/cms/program_list.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{% extends "richie/fullwidth.html" %}
{% load cms_tags extra_tags i18n %}
{% load cms_tags extra_tags i18n pagination_tags %}

{% block subheader_content %}
<div class="subheader__container">
Expand All @@ -19,7 +19,13 @@ <h1 class="subheader__title">{{ current_page.get_title }}</h1>

<div class="program-list__programs program-list__row">
<div class="program-glimpse-list">
{% for page in current_page.get_child_pages %}
{% if current_page.publisher_is_draft %}
{% autopaginate current_page.get_child_pages 100 as object_list %}
{% else %}
{% autopaginate current_page.get_child_pages.published.distinct 100 as object_list %}
{% endif %}

{% for page in object_list %}
{% if page.program %}
{% include "courses/cms/fragment_program_glimpse.html" with program=page.program %}
{% endif %}
Expand All @@ -28,6 +34,10 @@ <h1 class="subheader__title">{{ current_page.get_title }}</h1>
{% trans "No associated programs" %}
</p>
{% endfor %}

{% if object_list %}
{% paginate using "richie/pagination.html" %}
{% endif %}
</div>
</div>
</div>
Expand Down
59 changes: 59 additions & 0 deletions tests/apps/courses/test_templates_category_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""
End-to-end tests for the category list view
"""
from datetime import timedelta
from unittest import mock

from django.utils import timezone

from cms.test_utils.testcases import CMSTestCase

from richie.apps.core.factories import PageFactory, UserFactory
from richie.apps.courses.factories import CategoryFactory


class ListCategoryCMSTestCase(CMSTestCase):
"""
End-to-end test suite to validate the content and Ux of the category list view
"""

def test_templates_category_list_cms_content(self):
"""
Validate that the public website only displays categories that are currently published,
while staff users can see draft and unpublished categories.
"""
page = PageFactory(
template="courses/cms/category_list.html",
title__language="en",
should_publish=True,
)

CategoryFactory(page_parent=page, page_title="First category")
CategoryFactory(
page_parent=page, page_title="Second category", should_publish=True
)

# Publish with a publication date in the future
future = timezone.now() + timedelta(hours=1)
with mock.patch("cms.models.pagemodel.now", return_value=future):
CategoryFactory(
page_parent=page, page_title="Third category", should_publish=True
)

# Anonymous users should only see published categories
response = self.client.get(page.get_absolute_url())

self.assertEqual(response.status_code, 200)
self.assertNotContains(response, "First")
self.assertContains(response, "Second")
self.assertNotContains(response, "Third")

# Staff users can see draft and unpublished categories
user = UserFactory(is_staff=True, is_superuser=True)
self.client.login(username=user.username, password="password")

response = self.client.get(page.get_absolute_url())
self.assertEqual(response.status_code, 200)

for title in ["First", "Second", "Third"]:
self.assertContains(response, title)
57 changes: 57 additions & 0 deletions tests/apps/courses/test_templates_person_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""
End-to-end tests for the person list view
"""
from datetime import timedelta
from unittest import mock

from django.utils import timezone

from cms.test_utils.testcases import CMSTestCase

from richie.apps.core.factories import PageFactory, UserFactory
from richie.apps.courses.factories import PersonFactory


class ListPersonCMSTestCase(CMSTestCase):
"""
End-to-end test suite to validate the content and Ux of the person list view
"""

def test_templates_person_list_cms_content(self):
"""
Validate that the public website only displays persons that are currently published,
while staff users can see draft and unpublished persons.
"""
page = PageFactory(
template="courses/cms/person_list.html",
title__language="en",
should_publish=True,
)

PersonFactory(page_parent=page, page_title="First person")
PersonFactory(page_parent=page, page_title="Second person", should_publish=True)

# Publish with a publication date in the future
future = timezone.now() + timedelta(hours=1)
with mock.patch("cms.models.pagemodel.now", return_value=future):
PersonFactory(
page_parent=page, page_title="Third person", should_publish=True
)

# Anonymous users should only see published persons
response = self.client.get(page.get_absolute_url())

self.assertEqual(response.status_code, 200)
self.assertNotContains(response, "First")
self.assertContains(response, "Second")
self.assertNotContains(response, "Third")

# Staff users can see draft and unpublished persons
user = UserFactory(is_staff=True, is_superuser=True)
self.client.login(username=user.username, password="password")

response = self.client.get(page.get_absolute_url())
self.assertEqual(response.status_code, 200)

for title in ["First", "Second", "Third"]:
self.assertContains(response, title)
59 changes: 59 additions & 0 deletions tests/apps/courses/test_templates_program_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""
End-to-end tests for the program list view
"""
from datetime import timedelta
from unittest import mock

from django.utils import timezone

from cms.test_utils.testcases import CMSTestCase

from richie.apps.core.factories import PageFactory, UserFactory
from richie.apps.courses.factories import ProgramFactory


class ListProgramCMSTestCase(CMSTestCase):
"""
End-to-end test suite to validate the content and Ux of the program list view
"""

def test_templates_program_list_cms_content(self):
"""
Validate that the public website only displays programs that are currently published,
while staff users can see draft and unpublished programs.
"""
page = PageFactory(
template="courses/cms/program_list.html",
title__language="en",
should_publish=True,
)

ProgramFactory(page_parent=page, page_title="First program")
ProgramFactory(
page_parent=page, page_title="Second program", should_publish=True
)

# Publish with a publication date in the future
future = timezone.now() + timedelta(hours=1)
with mock.patch("cms.models.pagemodel.now", return_value=future):
ProgramFactory(
page_parent=page, page_title="Third program", should_publish=True
)

# Anonymous users should only see published programs
response = self.client.get(page.get_absolute_url())

self.assertEqual(response.status_code, 200)
self.assertNotContains(response, "First")
self.assertContains(response, "Second")
self.assertNotContains(response, "Third")

# Staff users can see draft and unpublished programs
user = UserFactory(is_staff=True, is_superuser=True)
self.client.login(username=user.username, password="password")

response = self.client.get(page.get_absolute_url())
self.assertEqual(response.status_code, 200)

for title in ["First", "Second", "Third"]:
self.assertContains(response, title)

0 comments on commit b3c46a8

Please sign in to comment.