11from django .contrib .auth import get_user_model
2+ from django .contrib .auth .models import Permission
23from django .contrib .staticfiles .testing import StaticLiveServerTestCase
4+ from django .test import tag
5+ from django .urls .base import reverse
6+ from django_loci .tests import TestAdminMixin
37from django_loci .tests .base .test_selenium import BaseTestDeviceAdminSelenium
48from selenium .webdriver .common .by import By
59from swapper import load_model
610
711from openwisp_users .tests .utils import TestOrganizationMixin
12+ from openwisp_utils .tests import SeleniumTestMixin
13+
14+ from .utils import TestGeoMixin
815
916Device = load_model ('config' , 'Device' )
1017Location = load_model ('geo' , 'Location' )
1118FloorPlan = load_model ('geo' , 'FloorPlan' )
1219DeviceLocation = load_model ('geo' , 'DeviceLocation' )
1320
1421
15- class TestDeviceAdminSelenium (
22+ # these tests are for geo elements on device admin
23+ @tag ('selenium_tests' )
24+ class TestDeviceAdminGeoSelenium (
1625 BaseTestDeviceAdminSelenium , TestOrganizationMixin , StaticLiveServerTestCase
1726):
1827 app_label = 'geo'
@@ -27,6 +36,10 @@ class TestDeviceAdminSelenium(
2736 def _get_prefix (cls ):
2837 return cls .inline_field_prefix
2938
39+ # set timeout to 5 seconds to allow enough time for presence of elements
40+ def wait_for_presence (self , by , value , timeout = 5 , driver = None ):
41+ return super ().wait_for_presence (by , value , timeout , driver )
42+
3043 def _fill_device_form (self ):
3144 org = self ._get_org ()
3245 self .find_element (by = By .NAME , value = 'mac_address' ).send_keys (
@@ -46,3 +59,54 @@ def _fill_device_form(self):
4659 )
4760 self .find_element (by = By .CLASS_NAME , value = 'select2-results__option' ).click ()
4861 super ()._fill_device_form ()
62+
63+
64+ @tag ('selenium_tests' )
65+ class TestDeviceAdminReadonly (
66+ TestGeoMixin ,
67+ TestAdminMixin ,
68+ SeleniumTestMixin ,
69+ StaticLiveServerTestCase ,
70+ ):
71+ browser = 'chrome'
72+ app_label = 'geo'
73+
74+ object_model = Device
75+ location_model = Location
76+ object_location_model = DeviceLocation
77+ permission_model = Permission
78+ user_model = get_user_model ()
79+
80+ # for these tests we need readonly user with view permissions.
81+ def setUp (self ):
82+ self .admin = self ._create_readonly_admin (
83+ username = self .admin_username ,
84+ password = self .admin_password ,
85+ models = [self .object_model , self .location_model , self .object_location_model ],
86+ )
87+
88+ def test_unsaved_changes_readonly (self ):
89+ self .login ()
90+ ol = self ._create_object_location ()
91+ path = reverse ('admin:config_device_change' , args = [ol .device .id ])
92+
93+ with self .subTest ('Alert should not be displayed without any change' ):
94+ self .open (path )
95+ self .hide_loading_overlay ()
96+ # The WebDriver automatically accepts the
97+ # beforeunload confirmation dialog. To verify the message,
98+ # we log it to the console and check its content.
99+ #
100+ # our own JS code sets e.returnValue when triggered
101+ # so we just need to ensure it's set as expected
102+ self .web_driver .execute_script (
103+ 'django.jQuery(window).on("beforeunload", function(e) {'
104+ ' console.warn(e.returnValue); });'
105+ )
106+ self .web_driver .refresh ()
107+ for entry in self .get_browser_logs ():
108+ if (
109+ entry ['level' ] == 'WARNING'
110+ and "You haven\' t saved your changes yet!" in entry ['message' ]
111+ ):
112+ self .fail ('Unsaved changes alert displayed without any change' )
0 commit comments