Skip to content

Commit b4d0b93

Browse files
committed
[fix] Fixed unsaved changes alert on device page
1 parent 4e16424 commit b4d0b93

File tree

3 files changed

+41
-28
lines changed

3 files changed

+41
-28
lines changed

openwisp_controller/config/static/config/js/relevant_templates.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,23 @@ django.jQuery(function ($) {
7171
},
7272
updateConfigTemplateField = function (templates) {
7373
var value = templates.join(","),
74-
templateField = templatesFieldName();
74+
templateField = templatesFieldName(),
75+
updateInitialValue = false;
7576
$(`input[name="${templateField}"]`).attr("value", value);
76-
if (pageLoading) {
77+
if (
78+
pageLoading ||
79+
// Handle cases where the AJAX request finishes after initial page load.
80+
// If we're editing an existing object and the initial value hasn't been set,
81+
// assign it now to avoid false positives in the unsaved changes warning.
82+
(!isAddingNewObject() &&
83+
django._owcInitialValues[templateField] === undefined)
84+
) {
7785
django._owcInitialValues[templateField] = value;
86+
updateInitialValue = true;
7887
}
79-
$("input.sortedm2m:first").trigger("change");
88+
$("input.sortedm2m:first").trigger("change", {
89+
updateInitialValue: updateInitialValue,
90+
});
8091
},
8192
getSelectedTemplates = function () {
8293
// Returns the selected templates from the sortedm2m input

openwisp_controller/config/static/config/js/widget.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -326,13 +326,7 @@
326326
}
327327
alert(message);
328328
}
329-
var contextField = $("#id_config-0-context");
330-
if (contextField.length) {
331-
var contextValue = JSON.parse(contextField.val());
332-
contextField.val(
333-
JSON.stringify(removeUnchangedDefaultValues(contextValue)),
334-
);
335-
}
329+
336330
if ($advancedEl.is(":hidden")) {
337331
return;
338332
}
@@ -494,8 +488,8 @@
494488
getDefaultValues(true);
495489
});
496490
}
497-
$(".sortedm2m-items").on("change", function () {
498-
getDefaultValues();
491+
$(".sortedm2m-items").on("change", function (event) {
492+
getDefaultValues(event.updateInitialValue === true);
499493
});
500494
$(".sortedm2m-items").on("sortstop", function () {
501495
getDefaultValues();

openwisp_controller/config/tests/test_selenium.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -523,24 +523,39 @@ class TestDeviceAdminUnsavedChanges(
523523
):
524524
browser = "chrome"
525525

526+
def _is_unsaved_changes_alert_present(self):
527+
for entry in self.get_browser_logs():
528+
if (
529+
entry["level"] == "WARNING"
530+
and "You haven't saved your changes yet!" in entry["message"]
531+
):
532+
return True
533+
return False
534+
535+
def _override_unsaved_changes_alert(self):
536+
self.web_driver.execute_script(
537+
'django.jQuery(window).on("beforeunload", function(e) {'
538+
" console.warn(e.returnValue); });"
539+
)
540+
526541
def test_unsaved_changes(self):
527542
"""
528543
Execute this test using Chrome instead of Firefox.
529544
Firefox automatically accepts the beforeunload alert, which makes it
530545
impossible to test the unsaved changes alert.
531546
"""
532547
self.login()
548+
self._create_template(default=True, default_values={"ssid": "default"})
533549
device = self._create_config(organization=self._get_org()).device
534550
path = reverse("admin:config_device_change", args=[device.id])
535551

536552
with self.subTest("Alert should not be displayed without any change"):
537553
self.open(path)
538554
self.hide_loading_overlay()
539-
try:
540-
WebDriverWait(self.web_driver, 1).until(EC.alert_is_present())
541-
except TimeoutException:
542-
pass
543-
else:
555+
self._override_unsaved_changes_alert()
556+
# Simulate navigating away from the page
557+
self.open(reverse("admin:index"))
558+
if self._is_unsaved_changes_alert_present():
544559
self.fail("Unsaved changes alert displayed without any change")
545560

546561
with self.subTest("Alert should be displayed after making changes"):
@@ -550,10 +565,9 @@ def test_unsaved_changes(self):
550565
#
551566
# our own JS code sets e.returnValue when triggered
552567
# so we just need to ensure it's set as expected
553-
self.web_driver.execute_script(
554-
'django.jQuery(window).on("beforeunload", function(e) {'
555-
" console.warn(e.returnValue); });"
556-
)
568+
self.open(path)
569+
self.hide_loading_overlay()
570+
self._override_unsaved_changes_alert()
557571
# simulate hand gestures
558572
self.find_element(by=By.TAG_NAME, value="body").click()
559573
self.find_element(by=By.NAME, value="name").click()
@@ -562,13 +576,7 @@ def test_unsaved_changes(self):
562576
# simulate hand gestures
563577
self.find_element(by=By.TAG_NAME, value="body").click()
564578
self.web_driver.refresh()
565-
for entry in self.get_browser_logs():
566-
if (
567-
entry["level"] == "WARNING"
568-
and "You haven't saved your changes yet!" in entry["message"]
569-
):
570-
break
571-
else:
579+
if not self._is_unsaved_changes_alert_present():
572580
self.fail("Unsaved changes code was not executed.")
573581

574582

0 commit comments

Comments
 (0)