#!/usr/bin/python3## Copyright (C) 2021 Red Hat, Inc.# SPDX-License-Identifier: LGPL-2.1-or-laterfrom anacondalib import VirtInstallMachineCase, pixel_tests_ignorefrom bugzilla_mock import (install_mock_bugzilla,set_mock_bugzilla_bugs,uninstall_mock_bugzilla,)from installer import Installerfrom testlib import nondestructive, test_main # pylint: disable=import-errorfrom utils import get_pretty_name@nondestructiveclass TestBasic(VirtInstallMachineCase):def testNavigation(self):"""Description:Verifies that all steps in the installer are accessible via 'Next' buttonExpected results:- All steps are reachable by clicking on the 'Next' button"""b = self.browserm = self.machinei = Installer(b, m)i.open()self.assertIn(b.attr("#app .pf-v6-c-page", "data-debug").lower(),["false", "true"])i.check_prerelease_info()# Do not start the installation in non-destructive tests as this performs non revertible changes# with the pages basically empty of common elements (as those are provided by the top-level installer widget)# we at least iterate over them to check this works as expectedi.reach(i.steps.REVIEW)# Ensure that the 'actual' UI process is running/self.assertIn("/usr/libexec/anaconda/webui-desktop", m.execute("ps aux"))def testSidebarNavigation(self):"""Description:Verifies navigation to previous steps using the sidebarExpected results:- All previous steps are reachable by clicking on the sidebar- Later steps are disabled in the sidebar"""b = self.browserm = self.machinei = Installer(b, m)i.open()i.check_prerelease_info()# Test that clicking on current step does not break navigationi.click_step_on_sidebar()i.reach(i.steps.REVIEW)# Test going backsteps = [i.steps.ACCOUNTS,i.steps.STORAGE_CONFIGURATION,i.steps.INSTALLATION_METHOD,i.steps.LANGUAGE,]for step in steps:if step not in i.steps.hidden_steps:i.click_step_on_sidebar(step)i.reach(i.steps.REVIEW)# Check disabling of later steps when going backi.reach_on_sidebar(i.steps.LANGUAGE)for step in [i.steps.ACCOUNTS,i.steps.STORAGE_CONFIGURATION,i.steps.INSTALLATION_METHOD,i.steps.REVIEW,]:i.check_sidebar_step_disabled(step)def testAboutModal(self):"""Description:Test the About modalExpected results:- The About modal is shown when clicking on the "About" item in the kebab menu- The About modal contains the correct information- The About modal can be closed"""b = self.browserm = self.machinei = Installer(b, m)i.open()# Obtain pretty name and versions from the CLIpretty_name = get_pretty_name(m)backend_version = m.execute("anaconda --version | cut -d ' ' -f 2 | tail -1").strip()webui_version = m.execute("cat /usr/local/share/cockpit/anaconda-webui/VERSION.txt").strip().split()[0]# Click on the kebabb.click("#toggle-kebab")# Click on the "About" item from the dropdownb.click("#about-modal-dropdown-item-about")# Expect PRETTY_NAME to be shown in modal titleb.wait_in_text("#about-modal-title", pretty_name)# Expect "Powered by Anaconda" to be shown in modal subtitleb.wait_in_text("#about-modal-subtitle", "Powered by Anaconda")# Expect About modal body to be shownb.wait_in_text("#backend-dt", "Anaconda")b.wait_in_text("#backend-dd", backend_version)b.wait_in_text("#webui-dt", "Anaconda WebUI")b.wait_in_text("#webui-dd", webui_version)# Expect button link for Anaconda project page to be shownb.wait_in_text("#anaconda-page-button", "Anaconda project page")# Pixel test the language stepb.assert_pixels(".pf-v6-c-about-modal-box","about-modal",ignore=[*pixel_tests_ignore, "#backend-dd","#webui-dd", "#about-modal-title"],)# Close about modalb.click(".pf-v6-c-button[aria-label='Close Dialog']")b.wait_not_present("#about-modal")def testReportIssue(self):"""Description:Test the Report Issue modalExpected results:- The Report Issue modal is shown when clicking on the "Report issue" item in the kebab menu- The Report Issue modal contains the correct information- The Report Issue modal can be closed"""b = self.browserm = self.machinei = Installer(b, m)i.open()b.wait_not_present("#user-issue-bz-report-modal")b.click("#toggle-kebab")b.click("#about-modal-dropdown-item-report")b.wait_visible("#user-issue-bz-report-modal")b.click("#user-issue-dialog-cancel-btn")b.wait_not_present("#user-issue-bz-report-modal")def testJsErrorHandling(self):"""Description:Test that the Error modal is shown when a JS error occursSetup:- Trigger a JS errorExpected results:- The Error modal is shown- The Error modal contains the correct information- The Journal contains the exception"""b = self.browserm = self.machinei = Installer(b, m)i.open()b.wait_not_present("#critical-error-bz-report-modal")b.eval_js("window.setTimeout(function() { myNonExistingFunction()}, 0);")b.wait_in_text("#critical-error-bz-report-modal-details", "myNonExistingFunction is not defined")b.wait_visible("button:contains('Next'):disabled")b.assert_pixels("#critical-error-bz-report-modal","js-error-modal",ignore=["#critical-error-bz-report-modal-review-log"])# Check the exception is present in the journalself.assertIn("myNonExistingFunction is not defined",m.execute("journalctl -b -t anaconda-webui"))def _open_critical_error_report_step1(self):b = self.browseri = Installer(b, self.machine)i.open()b.wait_not_present("#critical-error-bz-report-modal")b.eval_js("window.setTimeout(function() { myNonExistingFunction()}, 0);")b.wait_in_text("#critical-error-bz-report-modal-details", "myNonExistingFunction is not defined")b.wait_visible("#critical-error-bugzilla-apikey")def testBugzillaDuplicateDetection(self):"""Description:Test duplicate detection in the Bugzilla reporting flowSetup:- Install a mock python-bugzilla package that returns canned open bugs- Trigger a JS error to open the critical-error report modalExpected results:- After API key validation, potential duplicates are shown- Users can continue to create a new report- Back navigation returns to the duplicate list when matches exist- When no duplicates are found, the duplicates step is skipped"""b = self.browserm = self.machinedialog = "#critical-error-bz-report-modal"mock_bugs = [{"id": 2428210,"summary": "WebUI: org.fedoraproject.Anaconda.BootloaderInstallationError: boot loader install failed","status": "NEW",},{"id": 2491005,"summary": ("Installation of the system failed: Installing boot loader"" org.fedoraproject.Anaconda.BootloaderInstallationError:"" boot loader install failed"),"status": "NEW",},{"id": 2485664,"summary": ("Installation of the system failed: Installing boot loader"" org.fedoraproject.Anaconda.BootloaderInstallationError:"" boot loader install failed"),"status": "NEW",},]install_mock_bugzilla(m, mock_bugs)self.addCleanup(uninstall_mock_bugzilla, m)self._open_critical_error_report_step1()# Step 1: enter API key and continueb.set_input_text("#critical-error-bugzilla-apikey", "fake-valid-api-key")b.wait_visible(f"{dialog} button:contains('Next'):not([disabled])")b.click(f"{dialog} button:contains('Next')")# Step 2: duplicates listb.wait_visible("#critical-error-duplicates-alert")b.wait_in_text("#critical-error-duplicates-alert", "Potential duplicate bugs found")b.wait_visible("#critical-error-duplicates-list")b.wait_in_text("#critical-error-duplicate-2428210", "#2428210")b.wait_in_text("#critical-error-duplicate-2428210", "[NEW]")b.wait_in_text("#critical-error-duplicate-2491005", "#2491005")b.wait_in_text("#critical-error-duplicate-2485664", "#2485664")b.wait_visible("#critical-error-continue-new-btn")# Continue to create a new report (step 3)b.click("#critical-error-continue-new-btn")b.wait_visible("#critical-error-bug-summary")b.wait_not_present("#critical-error-duplicates-list")b.wait_visible(f"{dialog} button:contains('Report issue')")# Back returns to the duplicates step when matches existb.click(f"{dialog} button:contains('Back')")b.wait_visible("#critical-error-duplicates-list")b.wait_not_present("#critical-error-bug-summary")# Back from duplicates returns to API key entryb.click(f"{dialog} button:contains('Back')")b.wait_visible("#critical-error-bugzilla-apikey")b.wait_not_present("#critical-error-duplicates-list")# No duplicates: skip straight to bug detailsset_mock_bugzilla_bugs(m, [])b.set_input_text("#critical-error-bugzilla-apikey", "fake-valid-api-key")b.click(f"{dialog} button:contains('Next')")b.wait_visible("#critical-error-bug-summary")b.wait_not_present("#critical-error-duplicates-list")b.wait_visible(f"{dialog} button:contains('Report issue')")# Back skips the empty duplicates step and returns to API key entryb.click(f"{dialog} button:contains('Back')")b.wait_visible("#critical-error-bugzilla-apikey")b.wait_not_present("#critical-error-bug-summary")if __name__ == '__main__':test_main()