From 481a50717a34f6ed0241433b9d1db685f7d17b01 Mon Sep 17 00:00:00 2001
From: Muhammad Adeel Tajamul
<77053848+muhammadadeeltajamul@users.noreply.github.com>
Date: Thu, 29 Aug 2024 06:07:57 -0700
Subject: [PATCH] feat: updated content in course_update notification (#35373)
---
.../contentstore/tests/test_utils.py | 34 +++++++++++++++++++
cms/djangoapps/contentstore/utils.py | 30 ++++++++++++++--
.../notifications/base_notification.py | 3 +-
3 files changed, 63 insertions(+), 4 deletions(-)
diff --git a/cms/djangoapps/contentstore/tests/test_utils.py b/cms/djangoapps/contentstore/tests/test_utils.py
index 450040c803..9c478ddfe5 100644
--- a/cms/djangoapps/contentstore/tests/test_utils.py
+++ b/cms/djangoapps/contentstore/tests/test_utils.py
@@ -9,6 +9,7 @@ import ddt
from django.conf import settings
from django.test import TestCase
from django.test.utils import override_settings
+from edx_toggles.toggles.testutils import override_waffle_flag
from opaque_keys.edx.keys import CourseKey
from opaque_keys.edx.locator import CourseLocator, LibraryLocator
from path import Path as path
@@ -19,7 +20,11 @@ from user_tasks.models import UserTaskArtifact, UserTaskStatus
from cms.djangoapps.contentstore import utils
from cms.djangoapps.contentstore.tasks import ALL_ALLOWED_XBLOCKS, validate_course_olx
from cms.djangoapps.contentstore.tests.utils import TEST_DATA_DIR, CourseTestCase
+from cms.djangoapps.contentstore.utils import send_course_update_notification
+from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.tests.factories import GlobalStaffFactory, InstructorFactory, UserFactory
+from openedx.core.djangoapps.notifications.config.waffle import ENABLE_NOTIFICATIONS
+from openedx.core.djangoapps.notifications.models import CourseNotificationPreference, Notification
from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context
from xmodule.modulestore import ModuleStoreEnum # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order
@@ -927,3 +932,32 @@ class UpdateCourseDetailsTests(ModuleStoreTestCase):
utils.update_course_details(mock_request, self.course.id, payload, None)
mock_update.assert_called_once_with(self.course.id, payload, mock_request.user)
+
+
+@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True)
+class CourseUpdateNotificationTests(ModuleStoreTestCase):
+ """
+ Unit tests for the course_update notification.
+ """
+
+ def setUp(self):
+ """
+ Setup the test environment.
+ """
+ super().setUp()
+ self.user = UserFactory()
+ self.course = CourseFactory.create(org='testorg', number='testcourse', run='testrun')
+ CourseNotificationPreference.objects.create(user_id=self.user.id, course_id=self.course.id)
+
+ def test_course_update_notification_sent(self):
+ """
+ Test that the course_update notification is sent.
+ """
+ user = UserFactory()
+ CourseEnrollment.enroll(user=user, course_key=self.course.id)
+ assert Notification.objects.all().count() == 0
+ content = "
content
"
+ send_course_update_notification(self.course.id, content, self.user)
+ assert Notification.objects.all().count() == 1
+ notification = Notification.objects.first()
+ assert notification.content == "content
"
diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py
index 631ceeb270..17e94112ba 100644
--- a/cms/djangoapps/contentstore/utils.py
+++ b/cms/djangoapps/contentstore/utils.py
@@ -11,16 +11,19 @@ from datetime import datetime, timezone
from urllib.parse import quote_plus
from uuid import uuid4
+from bs4 import BeautifulSoup
from django.conf import settings
from django.core.exceptions import ValidationError
from django.urls import reverse
from django.utils import translation
+from django.utils.text import Truncator
from django.utils.translation import gettext as _
from eventtracking import tracker
from help_tokens.core import HelpUrlExpert
from lti_consumer.models import CourseAllowPIISharingInLTIFlag
from opaque_keys.edx.keys import CourseKey, UsageKey
from opaque_keys.edx.locator import LibraryLocator
+
from openedx.core.lib.teams_config import CONTENT_GROUPS_FOR_TEAMS, TEAM_SCHEME
from openedx_events.content_authoring.data import DuplicatedXBlockData
from openedx_events.content_authoring.signals import XBLOCK_DUPLICATED
@@ -2239,11 +2242,34 @@ def track_course_update_event(course_key, user, course_update_content=None):
tracker.emit(event_name, event_data)
+def clean_html_body(html_body):
+ """
+ Get html body, remove tags and limit to 500 characters
+ """
+ html_body = BeautifulSoup(Truncator(html_body).chars(500, html=True), 'html.parser')
+
+ tags_to_remove = [
+ "a", "link", # Link Tags
+ "img", "picture", "source", # Image Tags
+ "video", "track", # Video Tags
+ "audio", # Audio Tags
+ "embed", "object", "iframe", # Embedded Content
+ "script"
+ ]
+
+ # Remove the specified tags while keeping their content
+ for tag in tags_to_remove:
+ for match in html_body.find_all(tag):
+ match.unwrap()
+
+ return str(html_body)
+
+
def send_course_update_notification(course_key, content, user):
"""
Send course update notification
"""
- text_content = re.sub(r"(\s| |//)+", " ", html_to_text(content))
+ text_content = re.sub(r"(\s| |//)+", " ", clean_html_body(content))
course = modulestore().get_course(course_key)
extra_context = {
'author_id': user.id,
@@ -2252,7 +2278,7 @@ def send_course_update_notification(course_key, content, user):
notification_data = CourseNotificationData(
course_key=course_key,
content_context={
- "course_update_content": text_content if len(text_content.strip()) < 10 else "Click here to view",
+ "course_update_content": text_content,
**extra_context,
},
notification_type="course_updates",
diff --git a/openedx/core/djangoapps/notifications/base_notification.py b/openedx/core/djangoapps/notifications/base_notification.py
index 2c696ec60d..a417d45405 100644
--- a/openedx/core/djangoapps/notifications/base_notification.py
+++ b/openedx/core/djangoapps/notifications/base_notification.py
@@ -181,8 +181,7 @@ COURSE_NOTIFICATION_TYPES = {
'push': True,
'email_cadence': EmailCadence.DAILY,
'non_editable': [],
- 'content_template': _('<{p}>You have a new course update: '
- '<{strong}>{course_update_content}{strong}>{p}>'),
+ 'content_template': _('<{p}><{strong}>{course_update_content}{strong}>{p}>'),
'content_context': {
'course_update_content': 'Course update',
},