From b50d83739d7741fc21c659d0e34a95f7bfe96f4c Mon Sep 17 00:00:00 2001 From: Maria Grimaldi Date: Thu, 24 Feb 2022 17:19:08 -0400 Subject: [PATCH] feat: add broader range of exceptions for filters to use --- CHANGELOG.rst | 8 + openedx_filters/learning/filters.py | 187 +++++++++++++++++- .../learning/tests/test_filters.py | 89 +++++++++ 3 files changed, 275 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 75edc80d..0403d793 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -14,6 +14,14 @@ Change Log Unreleased ~~~~~~~~~~ +[0.6.0] - 2022-04-01 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Added +_____ + +* More significant exceptions for template interaction. + [0.5.1] - 2022-03-29 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/openedx_filters/learning/filters.py b/openedx_filters/learning/filters.py index 662df247..3b8f6692 100644 --- a/openedx_filters/learning/filters.py +++ b/openedx_filters/learning/filters.py @@ -165,11 +165,54 @@ class CertificateRenderStarted(OpenEdxPublicFilter): filter_type = "org.openedx.learning.certificate.render.started.v1" - class PreventCertificateRender(OpenEdxFilterException): + class RedirectToPage(OpenEdxFilterException): """ Custom class used to stop the certificate rendering process. """ + def __init__(self, message, redirect_to=""): + """ + Override init that defines specific arguments used in the certificate render process. + + Arguments: + message: error message for the exception. + redirect_to: URL to redirect to. + """ + super().__init__(message, redirect_to=redirect_to) + + class RenderAlternativeCertificate(OpenEdxFilterException): + """ + Custom class used to stop the certificate rendering process. + """ + + def __init__(self, message, template_name=""): + """ + Override init that defines specific arguments used in the certificate render process. + + Arguments: + message: error message for the exception. + template_name: template path of the new certificate. + """ + super().__init__(message, template_name=template_name) + + class RenderCustomResponse(OpenEdxFilterException): + """ + Custom class used to stop the certificate rendering process. + """ + + def __init__(self, message, response=None): + """ + Override init that defines specific arguments used in the certificate render process. + + Arguments: + message: error message for the exception. + response: custom response which will be returned by the certificate view. + """ + super().__init__( + message, + response=response, + ) + @classmethod def run_filter(cls, context, custom_template): """ @@ -217,17 +260,59 @@ class CourseAboutRenderStarted(OpenEdxPublicFilter): filter_type = "org.openedx.learning.course_about.render.started.v1" - class PreventCourseAboutRender(OpenEdxFilterException): + class RedirectToPage(OpenEdxFilterException): """ Custom class used to stop the course about rendering process. """ - def __init__(self, message, redirect_to=None): + def __init__(self, message, redirect_to=""): """ Override init that defines specific arguments used in the course about render process. + + Arguments: + message: error message for the exception. + redirect_to: URL to redirect to. """ super().__init__(message, redirect_to=redirect_to) + class RenderAlternativeCourseAbout(OpenEdxFilterException): + """ + Custom class used to stop the course about rendering process. + """ + + def __init__(self, message, course_about_template="", template_context=None): + """ + Override init that defines specific arguments used in the course about render process. + + Arguments: + message: error message for the exception. + course_about_template: template path rendered instead. + template_context: context used to the new course_about_template. + """ + super().__init__( + message, + course_about_template=course_about_template, + template_context=template_context, + ) + + class RenderCustomResponse(OpenEdxFilterException): + """ + Custom class used to stop the course about rendering process. + """ + + def __init__(self, message, response=None): + """ + Override init that defines specific arguments used in the course about render process. + + Arguments: + message: error message for the exception. + response: custom response which will be returned by the course about view. + """ + super().__init__( + message, + response=response, + ) + @classmethod def run_filter(cls, context, template_name): """ @@ -248,17 +333,59 @@ class CourseHomeRenderStarted(OpenEdxPublicFilter): filter_type = "org.openedx.learning.course_home.render.started.v1" - class PreventCourseHomeRender(OpenEdxFilterException): + class RedirectToPage(OpenEdxFilterException): """ - Custom class used to stop the course home render process. + Custom class used to stop the course home rendering process. """ - def __init__(self, message, redirect_to=None): + def __init__(self, message, redirect_to=""): """ Override init that defines specific arguments used in the course home render process. + + Arguments: + message: error message for the exception. + redirect_to: URL to redirect to. """ super().__init__(message, redirect_to=redirect_to) + class RenderAlternativeCourseHome(OpenEdxFilterException): + """ + Custom class used to stop the course home render process. + """ + + def __init__(self, message, course_home_template="", template_context=None): + """ + Override init that defines specific arguments used in the course home render process. + + Arguments: + message: error message for the exception. + course_home_template: template path rendered instead. + template_context: context used to the new course_home_template. + """ + super().__init__( + message, + course_home_template=course_home_template, + template_context=template_context, + ) + + class RenderCustomResponse(OpenEdxFilterException): + """ + Custom class used to stop the course home rendering process. + """ + + def __init__(self, message, response=None): + """ + Override init that defines specific arguments used in the course home render process. + + Arguments: + message: error message for the exception. + response: custom response which will be returned by the course home view. + """ + super().__init__( + message, + response=response, + ) + @classmethod def run_filter(cls, context, template_name): """ @@ -279,17 +406,59 @@ class DashboardRenderStarted(OpenEdxPublicFilter): filter_type = "org.openedx.learning.dashboard.render.started.v1" - class PreventDashboardRender(OpenEdxFilterException): + class RedirectToPage(OpenEdxFilterException): """ - Custom class used to stop the dashboard render process. + Custom class used to stop the dashboard rendering process. """ - def __init__(self, message, redirect_to=None): + def __init__(self, message, redirect_to=""): """ Override init that defines specific arguments used in the dashboard render process. + + Arguments: + message: error message for the exception. + redirect_to: URL to redirect to. """ super().__init__(message, redirect_to=redirect_to) + class RenderAlternativeDashboard(OpenEdxFilterException): + """ + Custom class used to stop the dashboard render process. + """ + + def __init__(self, message, dashboard_template="", template_context=None): + """ + Override init that defines specific arguments used in the dashboard render process. + + Arguments: + message: error message for the exception. + dashboard_template: template path rendered instead. + template_context: context used to the new dashboard_template. + """ + super().__init__( + message, + dashboard_template=dashboard_template, + template_context=template_context, + ) + + class RenderCustomResponse(OpenEdxFilterException): + """ + Custom class used to stop the dashboard rendering process. + """ + + def __init__(self, message, response=None): + """ + Override init that defines specific arguments used in the dashboard render process. + + Arguments: + message: error message for the exception. + response: custom response which will be returned by the dashboard view. + """ + super().__init__( + message, + response=response, + ) + @classmethod def run_filter(cls, context, template_name): """ diff --git a/openedx_filters/learning/tests/test_filters.py b/openedx_filters/learning/tests/test_filters.py index fbba1a50..6d331b24 100644 --- a/openedx_filters/learning/tests/test_filters.py +++ b/openedx_filters/learning/tests/test_filters.py @@ -3,6 +3,7 @@ """ from unittest.mock import Mock, patch +from ddt import data, ddt, unpack from django.test import TestCase from openedx_filters.learning.filters import ( @@ -19,6 +20,7 @@ ) +@ddt class TestCertificateFilters(TestCase): """ Test class to verify standard behavior of the certificate filters. @@ -75,6 +77,23 @@ def test_certificate_render_started(self): self.assertTupleEqual((context, template_name,), result) + @data( + (CertificateRenderStarted.RedirectToPage, {"redirect_to": "custom-certificate.pdf"}), + (CertificateRenderStarted.RenderAlternativeCertificate, {"template_name": "custom-certificate.html"}), + (CertificateRenderStarted.RenderCustomResponse, {"response": Mock()}), + ) + @unpack + def test_halt_certificate_render(self, CertificateException, attributes): + """ + Test for certificate exceptions attributes. + + Expected behavior: + - The exception must have the attributes specified. + """ + exception = CertificateException(message="You can't generate certificate", **attributes) + + self.assertDictContainsSubset(attributes, exception.__dict__) + class TestAuthFilters(TestCase): """ @@ -196,6 +215,7 @@ def test_course_unenrollment_started(self): self.assertEqual(expected_enrollment, enrollment) +@ddt class TestRenderingFilters(TestCase): """ Test class to verify standard behavior of the filters located in rendering views. @@ -252,6 +272,75 @@ def test_dashboard_render_started(self): self.assertTupleEqual((self.context, self.template_name,), result) + @data( + (DashboardRenderStarted.RedirectToPage, {"redirect_to": "custom-dashboard.html"}), + ( + DashboardRenderStarted.RenderAlternativeDashboard, + { + "dashboard_template": "custom-dasboard.html", + "template_context": {"user": Mock()}, + } + ), + (DashboardRenderStarted.RenderCustomResponse, {"response": Mock()}), + ) + @unpack + def test_halt_dashboard_render(self, dashboard_exception, attributes): + """ + Test for dashboard exceptions attributes. + + Expected behavior: + - The exception must have the attributes specified. + """ + exception = dashboard_exception(message="You can't access the dashboard", **attributes) + + self.assertDictContainsSubset(attributes, exception.__dict__) + + @data( + (CourseAboutRenderStarted.RedirectToPage, {"redirect_to": "custom-course-about.html"}), + ( + CourseAboutRenderStarted.RenderAlternativeCourseAbout, + { + "course_about_template": "custom-course-about.html", + "template_context": {"course_id": Mock()}, + } + ), + (CourseAboutRenderStarted.RenderCustomResponse, {"response": Mock()}), + ) + @unpack + def test_halt_course_about_render(self, course_about_exception, attributes): + """ + Test for course about exceptions attributes. + + Expected behavior: + - The exception must have the attributes specified. + """ + exception = course_about_exception(message="You can't access the course about", **attributes) + + self.assertDictContainsSubset(attributes, exception.__dict__) + + @data( + (CourseHomeRenderStarted.RedirectToPage, {"redirect_to": "custom-course-home.html"}), + ( + CourseHomeRenderStarted.RenderAlternativeCourseHome, + { + "course_home_template": "custom-course-home.html", + "template_context": {"course_id": Mock()}, + } + ), + (CourseHomeRenderStarted.RenderCustomResponse, {"response": Mock()}), + ) + @unpack + def test_halt_course_home_render(self, course_home_exception, attributes): + """ + Test for course home exceptions attributes. + + Expected behavior: + - The exception must have the attributes specified. + """ + exception = course_home_exception(message="You can't access the course home", **attributes) + + self.assertDictContainsSubset(attributes, exception.__dict__) + class TestCohortFilters(TestCase): """