@@ -162,6 +162,99 @@ class TestNetworkingCheckpoints(netlib.NetworkCase):
162162
163163 testlib .wait (checkpoint_was_destroyed )
164164
165+ def testCheckpointSessionStorageEventSuccess (self ):
166+ b = self .browser
167+
168+ self .login_and_go ("/network" )
169+ self .nm_checkpoints_enable ()
170+ b .wait_visible ("#networking" )
171+
172+ iface = 'cockpit1'
173+ self .add_veth (iface , dhcp_cidr = "10.111.114.2/20" )
174+ self .nm_activate_eth (iface )
175+ self .wait_for_iface (iface )
176+
177+ self .select_iface (iface )
178+ b .wait_visible ("#network-interface" )
179+
180+ # Verify sessionStorage is initially false or not set
181+ initial_value = b .call_js_func ("window.sessionStorage.getItem" , "cockpit_has_checkpoint" )
182+ self .assertIn (initial_value , [None , "false" ])
183+
184+ # Change IP settings which will trigger a checkpoint
185+ self .configure_iface_setting ('IPv4' )
186+ b .wait_visible ("#network-ip-settings-dialog" )
187+ b .select_from_dropdown ("#network-ip-settings-select-method" , "manual" )
188+ b .set_input_text ('#network-ip-settings-address-0' , "10.111.114.100" )
189+ b .set_input_text ('#network-ip-settings-netmask-0' , "20" )
190+
191+ # Click save, which triggers checkpoint creation
192+ b .click ("#network-ip-settings-save" )
193+
194+ # Verify sessionStorage becomes true during checkpoint operation
195+ def checkpoint_active ():
196+ value = b .call_js_func ("window.sessionStorage.getItem" , "cockpit_has_checkpoint" )
197+ return value == "true"
198+
199+ testlib .wait (checkpoint_active )
200+
201+ # Wait for operation to complete and sessionStorage to be cleared
202+ def checkpoint_cleared ():
203+ value = b .call_js_func ("window.sessionStorage.getItem" , "cockpit_has_checkpoint" )
204+ return value == "false"
205+
206+ testlib .wait (checkpoint_cleared )
207+
208+ def testCheckpointSessionStorageEventRollback (self ):
209+ b = self .browser
210+ m = self .machine
211+
212+ self .login_and_go ("/network" )
213+ self .nm_checkpoints_enable ()
214+ b .wait_visible ("#networking" )
215+
216+ iface = self .get_iface ("52:54:00:12:34:56" )
217+
218+ if "debian" in m .image :
219+ self .sed_file ("s/managed=false/managed=true/" , "/etc/NetworkManager/NetworkManager.conf" ,
220+ "systemctl restart NetworkManager" )
221+
222+ if m .image == "arch" :
223+ self .sed_file ("s/unmanaged-devices=interface-name:eth0//" , "/etc/NetworkManager/conf.d/noauto.conf" ,
224+ "systemctl restart NetworkManager" )
225+
226+ self .wait_for_iface (iface , prefix = "172." )
227+ self .select_iface (iface )
228+ b .wait_visible ("#network-interface" )
229+
230+ # Verify sessionStorage is initially false or not set
231+ initial_value = b .call_js_func ("window.sessionStorage.getItem" , "cockpit_has_checkpoint" )
232+ self .assertIn (initial_value , [None , "false" ])
233+
234+ # Disconnect interface which will trigger checkpoint and should cause rollback dialog
235+ self .wait_onoff ("label[for='interface-switch']" , val = True )
236+ self .toggle_onoff ("label[for='interface-switch']" )
237+
238+ # Verify sessionStorage becomes true during checkpoint operation
239+ def checkpoint_active ():
240+ value = b .call_js_func ("window.sessionStorage.getItem" , "cockpit_has_checkpoint" )
241+ return value == "true"
242+
243+ testlib .wait (checkpoint_active )
244+
245+ # Wait for dialog to appear (this happens when checkpoint_destroy fails)
246+ with b .wait_timeout (60 ):
247+ b .wait_visible ("#confirm-breaking-change-popup" )
248+
249+ # By the time dialog is visible, sessionStorage should already be cleared
250+ checkpoint_cleared_value = b .call_js_func ("window.sessionStorage.getItem" , "cockpit_has_checkpoint" )
251+ self .assertEqual (checkpoint_cleared_value , "false" )
252+
253+ # Keep the connection (rollback)
254+ b .click ("#confirm-breaking-change-popup button:contains('Keep connection')" )
255+
256+ b .wait_not_present ("#confirm-breaking-change-popup" )
257+
165258
166259if __name__ == '__main__' :
167260 testlib .test_main ()
0 commit comments