From 5ae9bc55ea46bf63aadca2d2c821c4fd058f7c91 Mon Sep 17 00:00:00 2001 From: Radek Vykydal Date: Fri, 10 Nov 2023 09:26:02 +0100 Subject: [PATCH 1/4] webui: make stepping back in tests more robust wrt hidden steps When going back let's use (in cases where we don't want to test the Back buttons specifically) sidebar navigation which is independent of hidden steps when going back. --- test/check-storage | 15 +++++---------- test/helpers/installer.py | 7 +++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/test/check-storage b/test/check-storage index 9cda4588ee..67186c672a 100755 --- a/test/check-storage +++ b/test/check-storage @@ -301,8 +301,7 @@ class TestStorage(anacondalib.VirtInstallMachineCase, StorageHelpers): # Go back to the Disk Configuration page and re-enter the review screen. # This should create again a new partitioning object and apply it # no matter how many partitioning objects were created before - i.back() - i.back() + i.reach_on_sidebar(i.steps.DISK_ENCRYPTION, parent_step=i.steps.DISK_CONFIGURATION) i.reach(i.steps.REVIEW) new_applied_partitioning = s.dbus_get_applied_partitioning() new_created_partitioning = s.dbus_get_created_partitioning() @@ -376,6 +375,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s = Storage(b, m) r = Review(b) + disk = "/dev/vda" dev = "vda" btrfsname = "btrfstest" @@ -428,9 +428,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) applied_partitioning = s.dbus_get_applied_partitioning() # When adding a new partition a new partitioning should be created - i.back() - i.back(previous_page=i.steps.CUSTOM_MOUNT_POINT) - i.back() + i.reach_on_sidebar(i.steps.INSTALLATION_METHOD) m.execute(f"sgdisk --new=0:0:0 {disk}") s.rescan_disks() @@ -800,9 +798,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) r.check_disk_row(dev, 3, "home, 15.0 GB: mount, /home") r.check_disk_row_not_present(dev, f"unused") - i.back() - i.back(previous_page=i.steps.CUSTOM_MOUNT_POINT) - i.back() + i.reach_on_sidebar(i.steps.INSTALLATION_METHOD) # Checks for nested btrfs subvolume tmp_mount = "/tmp/btrfs-mount-test" @@ -964,8 +960,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) r.check_disk_row(disk, 3, f"{vgname}-home, 8.12 GB: mount, /home") r.check_disk_row(disk, 4, f"{vgname}-swap, 902 MB: mount, swap") - i.back() - i.back(previous_page=i.steps.CUSTOM_MOUNT_POINT) + i.reach_on_sidebar(i.steps.CUSTOM_MOUNT_POINT, parent_step=i.steps.DISK_CONFIGURATION) # remove the /home row and check that row 3 is now swap s.remove_mountpoint_row(3) diff --git a/test/helpers/installer.py b/test/helpers/installer.py index 7c0e57cc1d..c0d8e348ed 100644 --- a/test/helpers/installer.py +++ b/test/helpers/installer.py @@ -138,6 +138,13 @@ def click_step_on_sidebar(self, step=None): step = step or self.get_current_page() self.browser.click(f"#{step}") + @log_step() + def reach_on_sidebar(self, target_page, parent_step=None): + if parent_step: + self.click_step_on_sidebar(parent_step) + self.click_step_on_sidebar(target_page) + self.wait_current_page(target_page) + def get_current_page(self): return self.browser.eval_js('window.location.hash;').replace('#/', '') or self.steps[0] From 6250afdac63c8afccc93076983ed0e0df157c73d Mon Sep 17 00:00:00 2001 From: Radek Vykydal Date: Fri, 10 Nov 2023 11:05:58 +0100 Subject: [PATCH 2/4] webui: keep information about parent steps in Installer class --- test/check-storage | 4 ++-- test/helpers/installer.py | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/test/check-storage b/test/check-storage index 67186c672a..ee68a58ca5 100755 --- a/test/check-storage +++ b/test/check-storage @@ -301,7 +301,7 @@ class TestStorage(anacondalib.VirtInstallMachineCase, StorageHelpers): # Go back to the Disk Configuration page and re-enter the review screen. # This should create again a new partitioning object and apply it # no matter how many partitioning objects were created before - i.reach_on_sidebar(i.steps.DISK_ENCRYPTION, parent_step=i.steps.DISK_CONFIGURATION) + i.reach_on_sidebar(i.steps.DISK_ENCRYPTION) i.reach(i.steps.REVIEW) new_applied_partitioning = s.dbus_get_applied_partitioning() new_created_partitioning = s.dbus_get_created_partitioning() @@ -960,7 +960,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) r.check_disk_row(disk, 3, f"{vgname}-home, 8.12 GB: mount, /home") r.check_disk_row(disk, 4, f"{vgname}-swap, 902 MB: mount, swap") - i.reach_on_sidebar(i.steps.CUSTOM_MOUNT_POINT, parent_step=i.steps.DISK_CONFIGURATION) + i.reach_on_sidebar(i.steps.CUSTOM_MOUNT_POINT) # remove the /home row and check that row 3 is now swap s.remove_mountpoint_row(3) diff --git a/test/helpers/installer.py b/test/helpers/installer.py index c0d8e348ed..7135d9baea 100644 --- a/test/helpers/installer.py +++ b/test/helpers/installer.py @@ -40,6 +40,10 @@ class InstallerSteps(UserDict): _steps_jump[REVIEW] = PROGRESS _steps_jump[PROGRESS] = [] + _parent_steps = {} + _parent_steps[DISK_ENCRYPTION] = DISK_CONFIGURATION + _parent_steps[CUSTOM_MOUNT_POINT] = DISK_CONFIGURATION + _steps_callbacks = {} _steps_callbacks[ACCOUNTS] = create_user @@ -139,9 +143,9 @@ def click_step_on_sidebar(self, step=None): self.browser.click(f"#{step}") @log_step() - def reach_on_sidebar(self, target_page, parent_step=None): - if parent_step: - self.click_step_on_sidebar(parent_step) + def reach_on_sidebar(self, target_page): + if target_page in self.steps._parent_steps: + self.click_step_on_sidebar(self.steps._parent_steps[target_page]) self.click_step_on_sidebar(target_page) self.wait_current_page(target_page) From b425a02f64fbfb04e9a4e1e33a11ea95eb4ce1e6 Mon Sep 17 00:00:00 2001 From: Radek Vykydal Date: Thu, 16 Nov 2023 09:50:40 +0100 Subject: [PATCH 3/4] webui: unify _steps_jump values to list --- test/helpers/installer.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/test/helpers/installer.py b/test/helpers/installer.py index 7135d9baea..9d7924416c 100644 --- a/test/helpers/installer.py +++ b/test/helpers/installer.py @@ -32,12 +32,12 @@ class InstallerSteps(UserDict): PROGRESS = "installation-progress" _steps_jump = {} - _steps_jump[WELCOME] = INSTALLATION_METHOD + _steps_jump[WELCOME] = [INSTALLATION_METHOD] _steps_jump[INSTALLATION_METHOD] = [DISK_ENCRYPTION, CUSTOM_MOUNT_POINT] - _steps_jump[DISK_ENCRYPTION] = ACCOUNTS - _steps_jump[CUSTOM_MOUNT_POINT] = ACCOUNTS - _steps_jump[ACCOUNTS] = REVIEW - _steps_jump[REVIEW] = PROGRESS + _steps_jump[DISK_ENCRYPTION] = [ACCOUNTS] + _steps_jump[CUSTOM_MOUNT_POINT] = [ACCOUNTS] + _steps_jump[ACCOUNTS] = [REVIEW] + _steps_jump[REVIEW] = [PROGRESS] _steps_jump[PROGRESS] = [] _parent_steps = {} @@ -67,7 +67,7 @@ def begin_installation(self, should_fail=False, confirm_erase=True): if should_fail: self.wait_current_page(current_page) else: - self.wait_current_page(self.steps._steps_jump[current_page]) + self.wait_current_page(self.steps._steps_jump[current_page][0]) def reach(self, target_page, hidden_steps=None): hidden_steps = hidden_steps or [] @@ -92,10 +92,7 @@ def next(self, should_fail=False, next_page=""): current_page = self.get_current_page() # If not explicitly specified, get the first item for next page from the steps dict if not next_page: - if isinstance(self.steps._steps_jump[current_page], list): - next_page = self.steps._steps_jump[current_page][0] - else: - next_page = self.steps._steps_jump[current_page] + next_page = self.steps._steps_jump[current_page][0] # Wait for a disk to be pre-selected before clicking 'Next'. # FIXME: Find a better way. From 35d79c71373cb148e96f101fa2cf2b25a95c68ed Mon Sep 17 00:00:00 2001 From: Radek Vykydal Date: Thu, 16 Nov 2023 09:52:23 +0100 Subject: [PATCH 4/4] webui: make tests usable for various cases of hidden steps Make Installer class aware of hidden steps and update the methods for moving between steps accordingly. --- test/check-basic | 13 +++++++------ test/check-storage | 33 ++++++++++++++++----------------- test/helpers/installer.py | 24 +++++++++++++++++------- test/helpers/utils.py | 3 ++- 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/test/check-basic b/test/check-basic index 3b2f502116..fe6116be54 100755 --- a/test/check-basic +++ b/test/check-basic @@ -78,7 +78,8 @@ class TestBasic(anacondalib.VirtInstallMachineCase): ] for step in steps: - i.click_step_on_sidebar(step) + if step not in i.hidden_steps: + i.click_step_on_sidebar(step) i.reach(i.steps.REVIEW) @@ -88,16 +89,16 @@ class TestBasic(anacondalib.VirtInstallMachineCase): i = Installer(b, m) r = Review(b) - pretend_live_iso(self) + pretend_live_iso(self, i) - # For live media the first screen is the installation-method - i.open(step="installation-method") + i.open() + i.reach(i.steps.INSTALLATION_METHOD) # Back button should be disabled on the first screen b.wait_visible(f"#installation-back-btn:not([aria-disabled={True}]") # For live media in the review screen language details should still be displayed - i.reach(i.steps.REVIEW, hidden_steps=[i.steps.ACCOUNTS]) + i.reach(i.steps.REVIEW) r.check_language("English (United States)") def testAboutModal(self): @@ -205,7 +206,7 @@ class TestBasic(anacondalib.VirtInstallMachineCase): s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) # FIXME: Remove PF5 specific selector: https://github.com/patternfly/patternfly-react/issues/9512 b.wait_not_present("#critical-error-bz-report-modal.pf-v5-c-modal-box") diff --git a/test/check-storage b/test/check-storage index ee68a58ca5..d1f0463dd9 100755 --- a/test/check-storage +++ b/test/check-storage @@ -41,7 +41,7 @@ class TestStorage(anacondalib.VirtInstallMachineCase, StorageHelpers): s = Storage(b, self.machine) i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) # Check the auto-selected disk's details s.check_single_disk_destination("vda", "16.1 GB") @@ -86,10 +86,10 @@ class TestStorage(anacondalib.VirtInstallMachineCase, StorageHelpers): self.addCleanup(m.execute, "killall blivet-gui") - pretend_live_iso(self) + pretend_live_iso(self, i) - # For live media the first screen is the installation-method - i.open(step="installation-method") + i.open() + i.reach(i.steps.INSTALLATION_METHOD) disk="vda" @@ -221,7 +221,6 @@ class TestStorage(anacondalib.VirtInstallMachineCase, StorageHelpers): p = Password(b, s.encryption_id_prefix) i.open() - # Language selection i.reach(i.steps.INSTALLATION_METHOD) @@ -334,7 +333,7 @@ class TestStorageExtraDisks(anacondalib.VirtInstallMachineCase, StorageHelpers): dev = dev.split("/")[-1] i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.wait_no_disks_detected_not_present() @@ -384,7 +383,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() s.select_mountpoint([(dev, True)]) @@ -470,7 +469,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() s.select_mountpoint([(dev, True)]) @@ -510,7 +509,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) # Select first only vdb disk and verify that the partitioning request is correct i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() @@ -589,7 +588,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() s.select_mountpoint([(dev1, True)]) @@ -654,7 +653,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() # select only vda and check that we don't try to unlock the LUKS partition on vdb @@ -703,7 +702,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() # select only vda and check that we don't try to unlock the LUKS partition on vdb @@ -759,7 +758,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() s.select_mountpoint([(dev, True)]) @@ -887,7 +886,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() s.wait_scenario_available("mount-point-mapping", False) @@ -919,7 +918,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() s.select_mountpoint([(dev, True)]) @@ -991,7 +990,7 @@ class TestStorageMountPoints(anacondalib.VirtInstallMachineCase, StorageHelpers) s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() s.select_mountpoint([(dev, True)]) @@ -1018,7 +1017,7 @@ class TestStorageMountPointsEFI(anacondalib.VirtInstallMachineCase): s.udevadm_settle() i.open() - i.next() + i.reach(i.steps.INSTALLATION_METHOD) s.rescan_disks() s.select_mountpoint([(dev, True)]) diff --git a/test/helpers/installer.py b/test/helpers/installer.py index 9d7924416c..ec41aef30d 100644 --- a/test/helpers/installer.py +++ b/test/helpers/installer.py @@ -48,10 +48,11 @@ class InstallerSteps(UserDict): _steps_callbacks[ACCOUNTS] = create_user class Installer(): - def __init__(self, browser, machine): + def __init__(self, browser, machine, hidden_steps=None): self.browser = browser self.machine = machine self.steps = InstallerSteps() + self.hidden_steps = hidden_steps or [] @log_step(snapshot_before=True) def begin_installation(self, should_fail=False, confirm_erase=True): @@ -69,8 +70,10 @@ def begin_installation(self, should_fail=False, confirm_erase=True): else: self.wait_current_page(self.steps._steps_jump[current_page][0]) - def reach(self, target_page, hidden_steps=None): - hidden_steps = hidden_steps or [] + def _previous_pages(self, page): + return [k for k, v in self.steps._steps_jump.items() if page in v] + + def reach(self, target_page): path = [] prev_pages = [target_page] current_page = self.get_current_page() @@ -78,11 +81,11 @@ def reach(self, target_page, hidden_steps=None): while current_page not in prev_pages: page = prev_pages[0] path.append(page) - prev_pages = [k for k, v in self.steps._steps_jump.items() if page in v] + prev_pages = self._previous_pages(page) while self.get_current_page() != target_page: next_page = path.pop() - if next_page not in hidden_steps: + if next_page not in self.hidden_steps: self.next(next_page=next_page) if next_page in self.steps._steps_callbacks: self.steps._steps_callbacks[next_page](self.browser, self.machine) @@ -93,6 +96,8 @@ def next(self, should_fail=False, next_page=""): # If not explicitly specified, get the first item for next page from the steps dict if not next_page: next_page = self.steps._steps_jump[current_page][0] + while next_page in self.hidden_steps: + next_page = self.steps._steps_jump[next_page][0] # Wait for a disk to be pre-selected before clicking 'Next'. # FIXME: Find a better way. @@ -124,12 +129,17 @@ def back(self, should_fail=False, previous_page=""): self.wait_current_page(current_page) else: if not previous_page: - previous_page = [k for k, v in self.steps._steps_jump.items() if current_page in v][0] + previous_page = self._previous_pages(current_page)[0] + while previous_page in self.hidden_steps: + previous_page = self._previous_pages(previous_page)[0] self.wait_current_page(previous_page) @log_step() - def open(self, step="installation-language"): + def open(self, step=None): + step = step or self.steps.WELCOME + while step in self.hidden_steps: + step = self.steps._steps_jump[step][0] self.browser.open(f"/cockpit/@localhost/anaconda-webui/index.html#/{step}") self.wait_current_page(step) # Ensure that the logo is visible before proceeding as pixel tests get racy otherwise diff --git a/test/helpers/utils.py b/test/helpers/utils.py index b62e85a200..2e6652d92d 100644 --- a/test/helpers/utils.py +++ b/test/helpers/utils.py @@ -26,7 +26,8 @@ def add_public_key(machine): machine.execute(f"chmod 700 {sysroot_ssh}") machine.write(authorized_keys, public_key, perm="0600") -def pretend_live_iso(test): +def pretend_live_iso(test, installer): + installer.hidden_steps.extend([installer.steps.ACCOUNTS, installer.steps.WELCOME]) test.restore_file('/run/anaconda/anaconda.conf') test.machine.execute("sed -i 's/type = BOOT_ISO/type = LIVE_OS/g' /run/anaconda/anaconda.conf")