Skip to content

Commit af4f504

Browse files
[change] Use relative URLs in notification widget #249
JS code to implement this change + one selenium test. Closes: #249 --------- Co-authored-by: Federico Capoano <[email protected]>
1 parent 22e6b1e commit af4f504

File tree

4 files changed

+79
-5
lines changed

4 files changed

+79
-5
lines changed

.github/workflows/build.yml

+2
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ jobs:
7373
SAMPLE_APP=1 ./runtests.py
7474
coverage run runtests.py --parallel
7575
coverage combine
76+
env:
77+
SELENIUM_HEADLESS: 1
7678

7779
- name: Upload Coverage
7880
run: coveralls --service=github

openwisp_notifications/static/openwisp-notifications/js/notifications.js

+20-4
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,9 @@ function notificationWidget($) {
195195
}
196196

197197
function notificationListItem(elem) {
198-
let klass,
199-
datetime = dateTimeStampToDateTimeLocaleString(new Date(elem.timestamp));
198+
let klass;
199+
const datetime = dateTimeStampToDateTimeLocaleString(new Date(elem.timestamp)),
200+
target_url = new URL(elem.target_url);
200201

201202
if (!notificationReadStatus.has(elem.id)) {
202203
if (elem.unread) {
@@ -207,8 +208,23 @@ function notificationWidget($) {
207208
}
208209
klass = notificationReadStatus.get(elem.id);
209210

211+
// Used to convert absolute URLs in notification messages to relative paths
212+
function convertMessageWithRelativeURL(htmlString) {
213+
const parser = new DOMParser(),
214+
doc = parser.parseFromString(htmlString, 'text/html'),
215+
links = doc.querySelectorAll('a');
216+
links.forEach((link) => {
217+
let url = link.getAttribute('href');
218+
if (url) {
219+
url = new URL(url);
220+
link.setAttribute('href', url.pathname);
221+
}
222+
});
223+
return doc.body.innerHTML;
224+
}
225+
210226
return `<div class="ow-notification-elem ${klass}" id=ow-${elem.id}
211-
data-location="${elem.target_url}" role="link" tabindex="0">
227+
data-location="${target_url.pathname}" role="link" tabindex="0">
212228
<div class="ow-notification-inner">
213229
<div class="ow-notification-meta">
214230
<div class="ow-notification-level-wrapper">
@@ -217,7 +233,7 @@ function notificationWidget($) {
217233
</div>
218234
<div class="ow-notification-date">${datetime}</div>
219235
</div>
220-
${elem.message}
236+
${convertMessageWithRelativeURL(elem.message)}
221237
</div>
222238
</div>`;
223239
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
2+
from selenium.webdriver.common.by import By
3+
from selenium.webdriver.support import expected_conditions as EC
4+
from selenium.webdriver.support.ui import WebDriverWait
5+
6+
from openwisp_notifications.swapper import load_model
7+
from openwisp_notifications.utils import _get_object_link
8+
from openwisp_users.tests.utils import TestOrganizationMixin
9+
from openwisp_utils.test_selenium_mixins import SeleniumTestMixin
10+
11+
Notification = load_model('Notification')
12+
13+
14+
class TestWidget(
15+
SeleniumTestMixin,
16+
TestOrganizationMixin,
17+
StaticLiveServerTestCase,
18+
):
19+
serve_static = True
20+
21+
def setUp(self):
22+
self.admin = self._create_admin(
23+
username=self.admin_username, password=self.admin_password
24+
)
25+
26+
def test_notification_relative_link(self):
27+
self.login()
28+
operator = super()._create_operator()
29+
data = dict(
30+
email_subject='Test Email subject',
31+
url='http://localhost:8000/admin/',
32+
)
33+
notification = Notification.objects.create(
34+
actor=self.admin,
35+
recipient=self.admin,
36+
description='Test Notification Description',
37+
verb='Test Notification',
38+
action_object=operator,
39+
target=operator,
40+
data=data,
41+
)
42+
self.web_driver.implicitly_wait(10)
43+
WebDriverWait(self.web_driver, 10).until(
44+
EC.visibility_of_element_located((By.ID, 'openwisp_notifications'))
45+
)
46+
self.web_driver.find_element(By.ID, 'openwisp_notifications').click()
47+
WebDriverWait(self.web_driver, 10).until(
48+
EC.visibility_of_element_located((By.CLASS_NAME, 'ow-notification-elem'))
49+
)
50+
notification_elem = self.web_driver.find_element(
51+
By.CLASS_NAME, 'ow-notification-elem'
52+
)
53+
data_location_value = notification_elem.get_attribute('data-location')
54+
self.assertEqual(
55+
data_location_value, _get_object_link(notification, 'target', False)
56+
)

requirements-test.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
openwisp-utils[qa] @ https://github.com/openwisp/openwisp-utils/tarball/master
1+
openwisp-utils[qa,selenium] @ https://github.com/openwisp/openwisp-utils/tarball/master
22
django-cors-headers~=4.0.0
33
django-redis~=5.2.0
44
channels_redis~=4.1.0

0 commit comments

Comments
 (0)