From a69ae8e71ef8b19a2db26d0698ca07e8609abfbe Mon Sep 17 00:00:00 2001 From: Martin Pitt Date: Thu, 22 Aug 2024 09:15:38 +0200 Subject: [PATCH] test: Wait until Disks table initialization before disk actions The disk kebabs keep jumping around while the Disk table initializes and re-renders, which is a race condition when trying to click on them with the actual browser mouse. So robustify the tests to wait for the table to be complete. This mitigates the issue, and also provides some nice extra validation. This was already done in a few places, generalize this into a `waitDisks()` helper. Unfortunately in some cases waiting for the entries is still not enough, but I can't figure out what else to wait on.. Do an extra sleep for the table to settle down. --- test/check-machines-disks | 20 +++++++++++++------- test/check-machines-storage-pools | 2 ++ test/machineslib.py | 11 +++++++++++ 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/test/check-machines-disks b/test/check-machines-disks index dc1fe43a5..7afe153e3 100755 --- a/test/check-machines-disks +++ b/test/check-machines-disks @@ -104,6 +104,7 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): b.wait_in_text("#vm-subVmTest1-system-state", "Running") self.goToVmPage("subVmTest1") + self.waitDisks(["vda", "vde", "vdf", "vdg"]) # Test non-persistent disks are not configurable b.wait_not_present("#vm-subVmTest1-disks-vdf-edit") @@ -182,6 +183,8 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): m.execute(f"virsh attach-disk --domain subVmTest1 --source {p1}/mydisk4 --target sdb --targetbus sata --persistent") b.reload() b.enter_page('/machines') + # expected devices after bus type change + self.waitDisks(["sda", "sdb", "vda", "vdg"]) openDialog("sdb") b.set_checked("#vm-subVmTest1-disks-sdb-edit-readonly", True) save("sdb", xfail="readonly sata disks are not supported") @@ -196,6 +199,9 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): # virsh attach-disk want send an event for offline VM changes b.reload() b.enter_page('/machines') + # expected devices after bus type change + self.waitDisks(["hda", "sdb", "vda", "vdg"]) + openDialog("hda") b._wait_present("#vm-subVmTest1-disks-hda-edit-bus-type option[value=sata]") self.assertFalse(b.is_present("#vm-subVmTest1-disks-hda-edit-bus-type option[value=virtio]")) @@ -224,6 +230,7 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): self.goToMainPage() self.createVm("subVmTest2", running=False, os="unknown") self.goToVmPage("subVmTest2") + self.waitDisks(["hda"], vm="subVmTest2") b.wait_in_text("#vm-subVmTest2-disks-hda-bus", "ide") @@ -296,7 +303,7 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): print("Restarting vm-subVmTest1, might take a while") self.performAction("subVmTest1", "forceReboot") - b.wait_visible("#vm-subVmTest1-disks-vda-device") + self.waitDisks(["vda"]) b.wait_not_present("#vm-subVmTest1-disks-vdc-device") # Check when no storage pool and adding existed disk @@ -1046,8 +1053,7 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): release_target(used_targets, target) permanent_targets = [t for t in used_targets if t not in transient_targets] - for target in permanent_targets: - b.wait_visible(f"#vm-subVmTest1-disks-{target}-device") + self.waitDisks(permanent_targets) # Check that creating a new volume in default_tmp does not by # accident use the defaults from defaultVol.iso. Those @@ -1515,6 +1521,7 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): # Test detaching non permanent disk of a running domain b.wait_in_text("#vm-subVmTest1-system-state", "Running") self.goToVmPage("subVmTest1") + self.waitDisks(["vda", "vdc", "vdd", "vde"]) self.deleteDisk("vdc", expect_path=vdc_path) # Wait for underlying VM's OS to detach the disk @@ -1553,10 +1560,7 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): b.reload() b.enter_page('/machines') self.waitPageInit() - b.wait_visible("#vm-subVmTest1-disks-sda-device") - b.wait_visible("#vm-subVmTest1-disks-sdb-device") - b.wait_visible("#vm-subVmTest1-disks-sdc-device") - b.wait_visible("#vm-subVmTest1-disks-vda-device") + self.waitDisks(["sda", "sdb", "sdc", "vda"]) def removeDiskAndChecks(target, path, removeFile=False, removeFileFail=False, removeFileNotPresent=False): self.dropdownAction(f"#vm-subVmTest1-disks-{target}-action-kebab", @@ -1651,6 +1655,8 @@ class TestMachinesDisks(machineslib.VirtualMachinesCase): b.wait_in_text("#vm-subVmTest1-system-state", "Running") self.goToVmPage("subVmTest1") + # wait until Disks have initialized; otherwise the kebabs jump around + self.waitDisks(["sda", "vda"]) self.VMInsertMediaDialog( self, diff --git a/test/check-machines-storage-pools b/test/check-machines-storage-pools index c3cd088cc..a00b827be 100755 --- a/test/check-machines-storage-pools +++ b/test/check-machines-storage-pools @@ -187,6 +187,8 @@ class TestMachinesStoragePools(machineslib.VirtualMachinesCase): self.goToMainPage() self.waitVmRow("subVmTest1") self.goToVmPage("subVmTest1") + self.waitDisks(["vda", "vdc"]) + self.deleteDisk("vdc") self.goToMainPage() b.click(".pf-v5-c-card .pf-v5-c-card__header button:contains(Storage pools)") diff --git a/test/machineslib.py b/test/machineslib.py index 13ad0f42b..c8b7078b9 100644 --- a/test/machineslib.py +++ b/test/machineslib.py @@ -343,6 +343,17 @@ def waitLogFile(self, logfile, expected_text): def waitGuestBooted(self, logfile): self.waitLogFile(logfile, "Welcome to Alpine Linux") + def waitDisks(self, expected_disks: list[str], vm="subVmTest1"): + """Wait until Disks table initialized on the details + + This prevents the kebabs from jumping around during re-renders, which + makes trying to click on them racy. + """ + for disk in expected_disks: + self.browser.wait_visible(f"#vm-{vm}-disks-{disk}-device") # type: ignore[attr-defined] + # HACK: we need to wait on *something* else, but no idea what.. + time.sleep(0.5) + class VirtualMachinesCase(testlib.MachineCase, VirtualMachinesCaseHelpers, storagelib.StorageHelpers, netlib.NetworkHelpers): def setUp(self):