From 8b2318bb76ea95a6add9844209641302ddd0831d Mon Sep 17 00:00:00 2001 From: resoluteCoder Date: Tue, 7 Apr 2026 11:21:32 -0500 Subject: [PATCH 1/3] fix: restore all 8 login UI tests by fixing SSO logout, credentials, and command palette --- test/ui/test_81_login.py | 13 +------ test/ui/utils/ui_utils.py | 74 +++++++++++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/test/ui/test_81_login.py b/test/ui/test_81_login.py index 7e37f23687..eed4990c2e 100644 --- a/test/ui/test_81_login.py +++ b/test/ui/test_81_login.py @@ -37,12 +37,10 @@ - name: Install dnsutils""" -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_unsubed_login( browser_setup: Any, lightspeed_logout_teardown: Any, screenshot_on_fail: Any, - close_editors: Any, ) -> None: """Test the login page for a user without subscription.""" driver, login_url = browser_setup @@ -83,12 +81,10 @@ def test_unsubed_login( assert body[i + 2].text == username -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_unsubed_admin_login( browser_setup: Any, lightspeed_logout_teardown: Any, screenshot_on_fail: Any, - close_editors: Any, ) -> None: """Test the login page for a user without subscription.""" driver, login_url = browser_setup @@ -133,12 +129,10 @@ def test_unsubed_admin_login( assert body[i + 3].text == "Role: administrator" -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_no_wca_user_login( browser_setup: Any, lightspeed_logout_teardown: Any, screenshot_on_fail: Any, - close_editors: Any, ) -> None: """Test the login page for a user with subscribed org that does not have wca set-up.""" driver, login_url = browser_setup @@ -202,7 +196,6 @@ def test_no_wca_user_login( assert body[i + 4].text == "Role: licensed user" -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_no_wca_admin_login( browser_setup: Any, lightspeed_logout_teardown: Any, @@ -256,7 +249,6 @@ def test_no_wca_admin_login( assert body[i + 2].text == "Role: administrator, licensed user" -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_login_page( browser_setup: Any, screenshot_on_fail: Any, @@ -300,7 +292,6 @@ def test_login_page( assert button.is_enabled() -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_sso_auth_flow( browser_setup: Any, screenshot_on_fail: Any, @@ -330,14 +321,13 @@ def test_sso_auth_flow( rh_button = click_and_wait( driver, login_button, - "//a[normalize-space(.)='Log in with Ansible Automation Platform']", + "//a[normalize-space(.)='Log in with Red Hat']", ) assert rh_button is not None assert rh_button.is_displayed() assert rh_button.is_enabled() -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_admin_portal_error( browser_setup: Any, screenshot_on_fail: Any, @@ -382,7 +372,6 @@ def test_admin_portal_error( admin_portal_logout(driver) -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_vscode_rhsso_auth_flow( browser_setup: Any, screenshot_on_fail: Any, diff --git a/test/ui/utils/ui_utils.py b/test/ui/utils/ui_utils.py index d72121b050..97ae2b0acb 100644 --- a/test/ui/utils/ui_utils.py +++ b/test/ui/utils/ui_utils.py @@ -30,6 +30,12 @@ LIGHTSPEED_USER = os.environ.get("LIGHTSPEED_USER", "") LIGHTSPEED_PASSWORD = os.environ.get("LIGHTSPEED_PASSWORD", "") +NO_SUB_USER = os.environ.get("NO_SUB_USER", "") +NO_SUB_PASSWORD = os.environ.get("NO_SUB_PASSWORD", "") +NO_SUB_ADMIN = os.environ.get("NO_SUB_ADMIN", "") +NO_WCA_USER = os.environ.get("NO_WCA_USER", "") +NO_WCA_PASSWORD = os.environ.get("NO_WCA_PASSWORD", "") +NO_WCA_ADMIN = os.environ.get("NO_WCA_ADMIN", "") # Move cursor to the "Explain the playbook with Ansible Lightspeed" menu item. # Note: The required number of DOWN key presses varies by VSCode version. @@ -185,7 +191,6 @@ def user_is_auth(driver: WebDriver) -> bool: return bool(elts) -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def sso_auth_flow( # noqa: PLR0913 driver: WebDriver, username: str = LIGHTSPEED_USER, @@ -207,8 +212,21 @@ def sso_auth_flow( # noqa: PLR0913 no_wca: Whether to skip WCA no_sub: Whether to skip subscription """ - user = LIGHTSPEED_USER - password = LIGHTSPEED_PASSWORD + if no_sub and admin_login: + user = NO_SUB_ADMIN + password = NO_SUB_PASSWORD + elif no_sub: + user = NO_SUB_USER + password = NO_SUB_PASSWORD + elif no_wca and admin_login: + user = NO_WCA_ADMIN + password = NO_WCA_PASSWORD + elif no_wca: + user = NO_WCA_USER + password = NO_WCA_PASSWORD + else: + user = LIGHTSPEED_USER + password = LIGHTSPEED_PASSWORD assert user assert password @@ -301,6 +319,11 @@ def redhat_logout(driver: WebDriver) -> None: assert logout_button.is_displayed() assert logout_button.is_enabled() logout_button.click() + # SSO shows a "Do you want to log out?" confirmation page + confirm_button = wait_displayed( + driver, "//input[@value='Logout'] | //button[normalize-space(.)='Logout']" + ) + confirm_button.click() def admin_portal_logout(driver: WebDriver) -> None: @@ -483,9 +506,22 @@ def vscode_connect( ansible_button = wait_displayed(driver, "//a[@aria-label='Ansible']", timeout=60) if device_login: # OAuth2 Device Flow - # in this case, give time for the command input to load correctly - vscode_run_command(driver, ">Ansible Lightspeed: Sign in with Red Hat") - if user_menu: # Use the VSCode Auth provider menu + vscode_run_command_f1(driver, "Ansible Lightspeed: Sign in with Red Hat") + driver.switch_to.default_content() + allow_button = wait_displayed( + driver, + "//a[normalize-space(.)='Allow']", + timeout=10, + ) + open_button = click_and_wait( + driver, + allow_button, + "//a[normalize-space(.)='Open']", + timeout=10, + ) + if open_button: + open_button.click() + elif user_menu: # Use the VSCode Auth provider menu user_button = click_and_wait( driver, ansible_button, @@ -1063,6 +1099,32 @@ def vscode_run_command( actions.send_keys(command_param, Keys.ENTER).perform() +def vscode_run_command_f1( + driver: WebDriver, command: str, command_param: str | None = None +) -> None: + """Run a command on vscode using F1 shortcut. + + Uses the F1 keyboard shortcut to open the command palette instead of + clicking the command center UI element, which is more resilient to + VSCode UI changes. + + Args: + driver: WebDriver instance + command: Command to run (will be prefixed with '>' if not present) + command_param: Parameter to pass to the command (argument) + """ + driver.switch_to.default_content() + if not command.startswith(">"): + command = ">" + command + actions = ActionChains(driver) + actions.send_keys(Keys.F1).perform() + time.sleep(0.5) + actions.send_keys(command).perform() + actions.send_keys(Keys.ENTER).perform() + if command_param: + actions.send_keys(command_param, Keys.ENTER).perform() + + def get_vscode_attribution(driver: WebDriver, prompt: str) -> dict[str, dict[str, str]]: """Return a dict for the attribution that is currently displayed. From 5c4552a60b85f55bc3127fc588b277198539af78 Mon Sep 17 00:00:00 2001 From: resoluteCoder Date: Tue, 7 Apr 2026 17:25:26 -0500 Subject: [PATCH 2/3] fix: restore lightspeed UI tests --- test/ui/fixtures/ui_fixtures.py | 2 +- test/ui/test_80_lightspeed.py | 33 +++--- test/ui/test_81_login.py | 2 - test/ui/test_82_lightspeed_trial.py | 4 +- test/ui/utils/ui_utils.py | 158 ++++++++++------------------ 5 files changed, 71 insertions(+), 128 deletions(-) diff --git a/test/ui/fixtures/ui_fixtures.py b/test/ui/fixtures/ui_fixtures.py index 52eb1784b3..dd4f385ed7 100644 --- a/test/ui/fixtures/ui_fixtures.py +++ b/test/ui/fixtures/ui_fixtures.py @@ -49,7 +49,7 @@ def is_container_healthy() -> bool: return result.returncode == 0 -@pytest.fixture(scope="session") +@pytest.fixture(scope="module") def browser_setup( request: pytest.FixtureRequest, ) -> Generator[tuple[WebDriver, str], None, None]: diff --git a/test/ui/test_80_lightspeed.py b/test/ui/test_80_lightspeed.py index c0f468b13b..75c01124e0 100644 --- a/test/ui/test_80_lightspeed.py +++ b/test/ui/test_80_lightspeed.py @@ -12,7 +12,7 @@ vscode_playbook_generation, vscode_prediction, vscode_role_generation, - vscode_run_command, + vscode_run_command_f1, wait_displayed, ) @@ -40,7 +40,7 @@ def vscode_login_wrapper(driver: Any) -> None: """Log in with VSCode at the scope of this file.""" - vscode_login(driver) + vscode_login(driver, device_login=True) global logged_in_flag # noqa: PLW0603 logged_in_flag = True @@ -74,11 +74,9 @@ def test_vscode_widget( ) -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_vscode_playbook_explanation( browser_setup: Any, screenshot_on_fail: Any, - close_editors: Any, ) -> None: """Test the playbook explanation feature from VSCode.""" driver, _ = browser_setup @@ -105,11 +103,9 @@ def test_vscode_playbook_explanation( assert phrase in explanation, msg -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_vscode_playbook_generation( browser_setup: Any, screenshot_on_fail: Any, - close_editors: Any, ) -> None: """Test the playbook generation feature from VSCode.""" driver, _ = browser_setup @@ -127,11 +123,9 @@ def test_vscode_playbook_generation( assert all(txt in playbook for txt in expected_playbook), "Error- bad playbook" -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_vscode_role_generation( browser_setup: Any, screenshot_on_fail: Any, - close_editors: Any, ) -> None: """Test the role generation feature from VSCode.""" driver, _ = browser_setup @@ -144,11 +138,9 @@ def test_vscode_role_generation( assert "ansible.builtin.package" in tasks -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") def test_vscode_lightspeed_explorer( browser_setup: Any, screenshot_on_fail: Any, - close_editors: Any, ) -> None: """Test the Lightspeed explorer view from VSCode.""" driver, _ = browser_setup @@ -156,27 +148,28 @@ def test_vscode_lightspeed_explorer( if not logged_in_flag: vscode_login_wrapper(driver) - vscode_run_command(driver, ">Ansible: Focus on Ansible Lightspeed View") - find_element_across_iframes( + vscode_run_command_f1(driver, "Ansible: Focus on Ansible Lightspeed View") + # verify logged-in state via the Accounts menu + accounts_button = wait_displayed(driver, "//a[@aria-label='Accounts']") + accounts_button.click() + wait_displayed( driver, - # After https://github.com/tomershinhar/selenium-vscode-container/pull/16 - # is deployed - # "//p[@class='user-content' and contains(normalize-space(.), 'Logged in as:')]", - "//*[contains(normalize-space(.), 'Logged in as:')]", + "//*[contains(normalize-space(.), 'lightspeed-test-user')]", + timeout=5, ) find_element_across_iframes( driver, - "//vscode-button[contains(normalize-space(.), 'Generate a playbook')]", + "//*[contains(normalize-space(.), 'Generate Playbook')]", ) find_element_across_iframes( driver, - "//vscode-button[contains(normalize-space(.), 'Explain the current playbook')]", + "//*[contains(normalize-space(.), 'Explain Playbook')]", ) find_element_across_iframes( driver, - "//vscode-button[contains(normalize-space(.), 'Generate a role')]", + "//*[contains(normalize-space(.), 'Generate Role')]", ) find_element_across_iframes( driver, - "//vscode-button[contains(normalize-space(.), 'Explain the current role')]", + "//*[contains(normalize-space(.), 'Explain Role')]", ) diff --git a/test/ui/test_81_login.py b/test/ui/test_81_login.py index eed4990c2e..f5955c8757 100644 --- a/test/ui/test_81_login.py +++ b/test/ui/test_81_login.py @@ -408,5 +408,3 @@ def test_vscode_rhsso_auth_flow( required_fields = ["url", "path", "source", "license", "score"] for attrib in content_match.values(): assert all(attrib[field] for field in required_fields) - # playbook = get_vscode_file_text(driver) - # assert all(text in playbook for text in ["ansible.builtin.package", "name: dnsutils"]) diff --git a/test/ui/test_82_lightspeed_trial.py b/test/ui/test_82_lightspeed_trial.py index 73dbfe3071..2325ba0c31 100644 --- a/test/ui/test_82_lightspeed_trial.py +++ b/test/ui/test_82_lightspeed_trial.py @@ -20,18 +20,16 @@ - name: install dnsutils""" -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") @pytest.mark.vscode_trial def test_vscode_trial_button( new_browser: Any, lightspeed_logout_teardown: Any, screenshot_on_fail: Any, - close_editors: Any, ) -> None: """Test the playbook explanation feature from vs-code.""" # We use a function scoped browser because the connection is different driver, _, _ = new_browser - vscode_login(driver, no_wca=True) + vscode_login(driver, no_wca=True, device_login=True) # Ensure we get the Trial button assert vscode_trial_button(driver, "playbook.yaml", PLAYBOOK_CONTENT) diff --git a/test/ui/utils/ui_utils.py b/test/ui/utils/ui_utils.py index 97ae2b0acb..5119d1d831 100644 --- a/test/ui/utils/ui_utils.py +++ b/test/ui/utils/ui_utils.py @@ -7,7 +7,6 @@ from collections.abc import Generator from typing import Any -import pytest from selenium.common import ( ElementClickInterceptedException, NoSuchElementException, @@ -191,6 +190,21 @@ def user_is_auth(driver: WebDriver) -> bool: return bool(elts) +def _get_sso_credentials( + *, admin_login: bool, no_wca: bool, no_sub: bool +) -> tuple[str, str]: + """Return (username, password) based on the login scenario.""" + if no_sub and admin_login: + return NO_SUB_ADMIN, NO_SUB_PASSWORD + if no_sub: + return NO_SUB_USER, NO_SUB_PASSWORD + if no_wca and admin_login: + return NO_WCA_ADMIN, NO_WCA_PASSWORD + if no_wca: + return NO_WCA_USER, NO_WCA_PASSWORD + return LIGHTSPEED_USER, LIGHTSPEED_PASSWORD + + def sso_auth_flow( # noqa: PLR0913 driver: WebDriver, username: str = LIGHTSPEED_USER, @@ -212,21 +226,9 @@ def sso_auth_flow( # noqa: PLR0913 no_wca: Whether to skip WCA no_sub: Whether to skip subscription """ - if no_sub and admin_login: - user = NO_SUB_ADMIN - password = NO_SUB_PASSWORD - elif no_sub: - user = NO_SUB_USER - password = NO_SUB_PASSWORD - elif no_wca and admin_login: - user = NO_WCA_ADMIN - password = NO_WCA_PASSWORD - elif no_wca: - user = NO_WCA_USER - password = NO_WCA_PASSWORD - else: - user = LIGHTSPEED_USER - password = LIGHTSPEED_PASSWORD + user, password = _get_sso_credentials( + admin_login=admin_login, no_wca=no_wca, no_sub=no_sub + ) assert user assert password @@ -354,17 +356,17 @@ def admin_portal_logout(driver: WebDriver) -> None: def vscode_login( driver: WebDriver, *, - device_login: bool = False, + device_login: bool = True, **kwargs: Any, ) -> None: """Go through the login process to ansible and vscode. Args: driver: WebDriver instance - device_login: Whether to use device login flow + device_login: Whether to use device login flow (kept for compatibility) **kwargs: Additional arguments passed to sso_auth_flow """ - vscode_connect(driver, device_login=device_login) + vscode_connect(driver) sso_auth_flow(driver, **kwargs) # switch back to vs-code @@ -485,83 +487,37 @@ def vscode_install_vsix(driver: WebDriver) -> None: def vscode_connect( driver: WebDriver, *, - user_menu: bool = False, - device_login: bool = False, + device_login: bool = True, install_vsix: bool = True, ) -> None: - """Go to the vscode ansible page and click the "connect" button. + """Go to the vscode ansible page and initiate the login flow. + + Uses the OAuth2 Device Flow via the F1 command palette. Args: driver: WebDriver instance - user_menu: Whether to use the VSCode Auth provider menu - device_login: Whether to use OAuth2 Device Flow + device_login: Whether to use device login flow (kept for compatibility) install_vsix: Whether to install the VSIX extension """ driver.get("http://127.0.0.1:8080") - # we rely on container backed in auto installation logic for our extension - # if install_vsix: - # vscode_install_vsix(driver) - - ansible_button = wait_displayed(driver, "//a[@aria-label='Ansible']", timeout=60) - - if device_login: # OAuth2 Device Flow - vscode_run_command_f1(driver, "Ansible Lightspeed: Sign in with Red Hat") - driver.switch_to.default_content() - allow_button = wait_displayed( - driver, - "//a[normalize-space(.)='Allow']", - timeout=10, - ) - open_button = click_and_wait( - driver, - allow_button, - "//a[normalize-space(.)='Open']", - timeout=10, - ) - if open_button: - open_button.click() - elif user_menu: # Use the VSCode Auth provider menu - user_button = click_and_wait( - driver, - ansible_button, - "//div[@aria-label='Accounts - Sign in requested']", - timeout=10, - ) - if user_button: - connect_button = click_and_wait( - driver, - user_button, - "//a[normalize-space(.)='Sign in with Ansible Lightspeed to use Ansible (1)']", - ) - if connect_button: - open_button = click_and_wait( - driver, - connect_button, - "//a[normalize-space(.)='Open']", - timeout=10, - ) - if open_button: - open_button.click() - else: - ansible_button.click() - connect_button = get_connect_button(driver) - connect_button.click() - driver.switch_to.default_content() - allow_button = wait_displayed( - driver, - "//a[normalize-space(.)='Allow']", - timeout=10, - ) - open_button = click_and_wait( - driver, - allow_button, - "//a[normalize-space(.)='Open']", - timeout=10, - ) + wait_displayed(driver, "//a[@aria-label='Ansible']", timeout=60) - if open_button: - open_button.click() + vscode_run_command_f1(driver, "Ansible Lightspeed: Sign in with Red Hat") + driver.switch_to.default_content() + allow_button = wait_displayed( + driver, + "//a[normalize-space(.)='Allow']", + timeout=10, + ) + open_button = click_and_wait( + driver, + allow_button, + "//a[normalize-space(.)='Open']", + timeout=10, + ) + if open_button: + open_button.click() driver.switch_to.window(driver.window_handles[-1]) @@ -794,7 +750,7 @@ def vscode_trial_button( actions.perform() max_attempts = 4 for n in range(max_attempts): - vscode_run_command(driver, ">Ansible Lightspeed: Inline suggestion trigger") + vscode_run_command_f1(driver, "Ansible Lightspeed: Inline suggestion trigger") time.sleep(0.5) try: return wait_displayed( @@ -863,18 +819,7 @@ def vscode_explanation(driver: WebDriver) -> str: timeout=60, ) text_window.click() - # right-click - actions = ActionChains(driver) - actions.context_click(text_window).perform() - - # Move cursor to the "Explain the playbook with Ansible Lightspeed" menu item. - # Note: The required number of DOWN key presses varies by VSCode version. - # Update the following line if VSCode's context menu items change. - for _ in range(POSITION_OF_ANSIBLE_EXPLAIN): - actions.send_keys(Keys.DOWN) - - actions.send_keys(Keys.ENTER) - actions.perform() + vscode_run_command_f1(driver, "Explain the playbook with Ansible Lightspeed") time.sleep(20) # move to new iframe # NOTE: If the test fails at this point (Explain panel doesn't appear), @@ -911,7 +856,7 @@ def vscode_playbook_generation(driver: WebDriver, task: str) -> tuple[str, str]: Tuple of (steps, playbook) text """ # run gen command - vscode_run_command(driver, ">Ansible Lightspeed: Playbook generation") + vscode_run_command_f1(driver, "Ansible Lightspeed: Playbook generation") title = find_element_across_iframes( driver, "//h2[contains(text(), 'Create a playbook with Ansible Lightspeed')]", @@ -981,7 +926,7 @@ def vscode_role_generation(driver: WebDriver, task: str) -> tuple[str, str]: Tuple of (steps, tasks) text """ # run gen command - vscode_run_command(driver, ">Ansible Lightspeed: Role generation") + vscode_run_command_f1(driver, "Ansible Lightspeed: Role generation") title = find_element_across_iframes( driver, "//h2[contains(text(), 'Create a role with Ansible Lightspeed')]", @@ -1120,7 +1065,16 @@ def vscode_run_command_f1( actions.send_keys(Keys.F1).perform() time.sleep(0.5) actions.send_keys(command).perform() - actions.send_keys(Keys.ENTER).perform() + command_label = command.lstrip(">") + try: + item = wait_displayed( + driver, + f"//div[@class='quick-input-list']//span[contains(normalize-space(.), '{command_label}')]", + timeout=3, + ) + item.click() + except (TimeoutException, TimeOutError): # pragma: no cover + actions.send_keys(Keys.ENTER).perform() if command_param: actions.send_keys(command_param, Keys.ENTER).perform() From 82682be220cb0bc5e5a2ea40989f275e7d52032c Mon Sep 17 00:00:00 2001 From: resoluteCoder Date: Fri, 10 Apr 2026 07:53:00 -0500 Subject: [PATCH 3/3] fix: remove SaaS web portal tests and unused multi-provider test --- test/ui/test_80_lightspeed.py | 34 ----- test/ui/test_81_login.py | 218 ---------------------------- test/ui/test_82_lightspeed_trial.py | 35 ----- test/ui/utils/ui_utils.py | 110 +------------- 4 files changed, 3 insertions(+), 394 deletions(-) delete mode 100644 test/ui/test_82_lightspeed_trial.py diff --git a/test/ui/test_80_lightspeed.py b/test/ui/test_80_lightspeed.py index 75c01124e0..8f0af9a649 100644 --- a/test/ui/test_80_lightspeed.py +++ b/test/ui/test_80_lightspeed.py @@ -30,11 +30,6 @@ tasks: - name: install dnsutils""" -MULTI_SUGGESTIONS_PLAYBOOK = """--- -- name: Playbook - hosts: all -tasks: - - name: Install dnsutils""" logged_in_flag = False @@ -45,35 +40,6 @@ def vscode_login_wrapper(driver: Any) -> None: logged_in_flag = True -# @pytest.mark.flaky(reruns=6, reruns_delay=10) -@pytest.mark.skip(reason="See https://redhat.atlassian.net/browse/AAP-67210") -def test_vscode_widget( - browser_setup: Any, - screenshot_on_fail: Any, - close_editors: Any, -) -> None: - """Test that the vs-code widget shows up and works correctly. - - Tests widget behavior when multiple suggestion extensions are installed. - """ - driver, _ = browser_setup - - vscode_login_wrapper(driver) - vscode_prediction( - driver, - "playbook.yaml", - MULTI_SUGGESTIONS_PLAYBOOK, - accept=False, - mutil_provider=True, - ) - # validate the widget is working correctly - wait_displayed( - driver, - "//span[contains(normalize-space(.), 'pilot')]", - timeout=20, - ) - - def test_vscode_playbook_explanation( browser_setup: Any, screenshot_on_fail: Any, diff --git a/test/ui/test_81_login.py b/test/ui/test_81_login.py index f5955c8757..e7079d6806 100644 --- a/test/ui/test_81_login.py +++ b/test/ui/test_81_login.py @@ -30,224 +30,6 @@ tasks: - name: install dnsutils""" -MULTI_SUGGESTIONS_PLAYBOOK = """--- -- name: Playbook - hosts: all -tasks: - - name: Install dnsutils""" - - -def test_unsubed_login( - browser_setup: Any, - lightspeed_logout_teardown: Any, - screenshot_on_fail: Any, -) -> None: - """Test the login page for a user without subscription.""" - driver, login_url = browser_setup - # here we should not be logged in - driver.get(login_url) - title = wait_displayed(driver, "//h1", timeout=10) - assert ( - title.text - == "Log in to Red Hat Ansible Lightspeed with IBM watsonx Code Assistant" - ) - # now we log in validate we still can't get to the admin portal - redhat_button = wait_displayed( - driver, - "//a[normalize-space(.)='Log in with Red Hat']", - ) - redhat_button.click() - # since we logged out, we need to go through RHSSO again - assert "redhat.com/auth" in driver.current_url - username = sso_auth_flow(driver, no_sub=True) - # set logout as teardown - lightspeed_logout_teardown(driver) - wait_displayed(driver, f"//p[contains(normalize-space(.), '{username}')]") - title = driver.find_element(by="xpath", value="//h1") - assert ( - title.text == "Your organization doesn't have access to " - "Red Hat Ansible Lightspeed with IBM watsonx Code Assistant." - ) - body = driver.find_elements(by="xpath", value="//p") - i = 0 - assert ( - body[i].text == "Your organization doesn't have access to " - "Red Hat Ansible Lightspeed with IBM watsonx Code Assistant." - ) - assert ( - body[i + 1].text - == "Contact your Red Hat Organization's administrator for more information." - ) - assert body[i + 2].text == username - - -def test_unsubed_admin_login( - browser_setup: Any, - lightspeed_logout_teardown: Any, - screenshot_on_fail: Any, -) -> None: - """Test the login page for a user without subscription.""" - driver, login_url = browser_setup - # here we should not be logged in - driver.get(login_url) - title = wait_displayed(driver, "//h1", timeout=10) - assert ( - title.text - == "Log in to Red Hat Ansible Lightspeed with IBM watsonx Code Assistant" - ) - # now we log in validate we still can't get to the admin portal - redhat_button = wait_displayed( - driver, - "//a[normalize-space(.)='Log in with Red Hat']", - ) - redhat_button.click() - # since we logged out, we need to go through RHSSO again - assert "redhat.com/auth" in driver.current_url - username = sso_auth_flow(driver, no_sub=True, admin_login=True) - # set logout as teardown - lightspeed_logout_teardown(driver) - wait_displayed(driver, f"//p[contains(normalize-space(.), '{username}')]") - title = driver.find_element(by="xpath", value="//h1") - assert ( - title.text - == "Your organization doesn't have access to Red Hat Ansible Lightspeed " - "with IBM watsonx Code Assistant." - ) - body = driver.find_elements(by="xpath", value="//p") - i = 0 - assert ( - body[i].text - == "Your organization doesn't have access to Red Hat Ansible Lightspeed with " - "IBM watsonx Code Assistant." - ) - assert ( - body[i + 1].text == "You do not have an Active subscription to Ansible " - "Automation Platform which is required to use Red Hat Ansible Lightspeed " - "with IBM watsonx Code Assistant." - ) - assert body[i + 2].text == username - assert body[i + 3].text == "Role: administrator" - - -def test_no_wca_user_login( - browser_setup: Any, - lightspeed_logout_teardown: Any, - screenshot_on_fail: Any, -) -> None: - """Test the login page for a user with subscribed org that does not have wca set-up.""" - driver, login_url = browser_setup - # here we should not be logged in - driver.get(login_url) - title = wait_displayed(driver, "//h1", timeout=10) - assert ( - title.text - == "Log in to Red Hat Ansible Lightspeed with IBM watsonx Code Assistant" - ) - # now we log in validate we still can't get to the admin portal - redhat_button = wait_displayed( - driver, - "//a[normalize-space(.)='Log in with Red Hat']", - ) - redhat_button.click() - # since we logged out, we need to go through RHSSO again - assert "redhat.com/auth" in driver.current_url - username = sso_auth_flow(driver, no_wca=True) - # set logout as teardown - lightspeed_logout_teardown(driver) - title = driver.find_element(by="xpath", value="//h1") - body = driver.find_elements(by="xpath", value="//p") - # wait for all required redirects happens before continue - time.sleep(5) - if driver.current_url.endswith("/trial/"): - # Trial case - assert title.text.startswith( - "Red Hat Ansible Lightspeed with IBM watsonx Code Assistant", - ) - assert any( - "Start a trial to Ansible Lightspeed with IBM watsonx Code Assistant" - in i.text - for i in body - ) - else: - wait_displayed(driver, f"//p[contains(normalize-space(.), '{username}')]") - assert ( - title.text == "You are a licensed Red Hat Ansible Lightspeed with IBM " - "watsonx Code Assistant user but your " - "administrator has not configured the service for your organization.\n" - "Contact your organization administrator to have them complete Red Hat " - "Ansible Lightspeed with IBM watsonx Code Assistant configuration." - ) - i = 0 - assert ( - body[i].text - == "You are a licensed Red Hat Ansible Lightspeed with IBM watsonx Code Assistant " - "user but your administrator has not configured the service for your organization." - ) - assert ( - body[i + 1].text == "Contact your organization administrator to have them " - "complete Red Hat Ansible Lightspeed " - "with IBM watsonx Code Assistant configuration." - ) - assert ( - body[i + 2].text - == "Contact your Red Hat Organization's administrator for more information." - ) - assert body[i + 3].text == username - assert body[i + 4].text == "Role: licensed user" - - -def test_no_wca_admin_login( - browser_setup: Any, - lightspeed_logout_teardown: Any, - screenshot_on_fail: Any, -) -> None: - """Test the login page for an admin user with subscribed org that does not have wca set-up.""" - driver, login_url = browser_setup - # here we should not be logged in - driver.get(login_url) - title = wait_displayed(driver, "//h1", timeout=10) - assert ( - title.text - == "Log in to Red Hat Ansible Lightspeed with IBM watsonx Code Assistant" - ) - # now we log in validate we still can't get to the admin portal - redhat_button = wait_displayed( - driver, - "//a[normalize-space(.)='Log in with Red Hat']", - ) - redhat_button.click() - # since we logged out, we need to go through RHSSO again - assert "redhat.com/auth" in driver.current_url - username = sso_auth_flow(driver, no_wca=True, admin_login=True) - # set logout as teardown - lightspeed_logout_teardown(driver) - wait_displayed(driver, f"//p[contains(normalize-space(.), '{username}')]") - title = driver.find_element(by="xpath", value="//h1") - assert title.text == "Red Hat Ansible Lightspeed with IBM watsonx Code Assistant" - body = driver.find_elements(by="xpath", value="//p") - if driver.current_url.endswith("/trial/"): - # Trial case - assert title.text.startswith( - "Red Hat Ansible Lightspeed with IBM watsonx Code Assistant", - ) - assert any( - "This will only apply to you and will not affect your organization." - in i.text - for i in body - ) - else: - i = 0 - assert ( - body[i].text == "You are a Red Hat organization administrator for " - "Red Hat Ansible Lightspeed with IBM watsonx Code Assistant." - " IBM watsonx Code Assistant" - " model settings have not been configured for your organization. Click here " - "to access the Red Hat Ansible Lightspeed with IBM watsonx Code Assistant " - "admin portal to complete configuration." - ) - assert body[i + 1].text == username - assert body[i + 2].text == "Role: administrator, licensed user" - def test_login_page( browser_setup: Any, diff --git a/test/ui/test_82_lightspeed_trial.py b/test/ui/test_82_lightspeed_trial.py deleted file mode 100644 index 2325ba0c31..0000000000 --- a/test/ui/test_82_lightspeed_trial.py +++ /dev/null @@ -1,35 +0,0 @@ -"""This module is for testing the Ansible Lightspeed Trial functionality.""" - -# pylint: disable=E0401, W0613, R0801, W0603 -from typing import Any - -import pytest - -from test.ui.utils.ui_utils import vscode_login, vscode_trial_button - -pytestmark = pytest.mark.lightspeed - - -PLAYBOOK_CONTENT = """ ---- -- name: example - hosts: all -become: true - -tasks: -- name: install dnsutils""" - - -@pytest.mark.vscode_trial -def test_vscode_trial_button( - new_browser: Any, - lightspeed_logout_teardown: Any, - screenshot_on_fail: Any, -) -> None: - """Test the playbook explanation feature from vs-code.""" - # We use a function scoped browser because the connection is different - driver, _, _ = new_browser - - vscode_login(driver, no_wca=True, device_login=True) - # Ensure we get the Trial button - assert vscode_trial_button(driver, "playbook.yaml", PLAYBOOK_CONTENT) diff --git a/test/ui/utils/ui_utils.py b/test/ui/utils/ui_utils.py index 5119d1d831..17f25f82f6 100644 --- a/test/ui/utils/ui_utils.py +++ b/test/ui/utils/ui_utils.py @@ -5,7 +5,6 @@ import os import time from collections.abc import Generator -from typing import Any from selenium.common import ( ElementClickInterceptedException, @@ -29,13 +28,6 @@ LIGHTSPEED_USER = os.environ.get("LIGHTSPEED_USER", "") LIGHTSPEED_PASSWORD = os.environ.get("LIGHTSPEED_PASSWORD", "") -NO_SUB_USER = os.environ.get("NO_SUB_USER", "") -NO_SUB_PASSWORD = os.environ.get("NO_SUB_PASSWORD", "") -NO_SUB_ADMIN = os.environ.get("NO_SUB_ADMIN", "") -NO_WCA_USER = os.environ.get("NO_WCA_USER", "") -NO_WCA_PASSWORD = os.environ.get("NO_WCA_PASSWORD", "") -NO_WCA_ADMIN = os.environ.get("NO_WCA_ADMIN", "") - # Move cursor to the "Explain the playbook with Ansible Lightspeed" menu item. # Note: The required number of DOWN key presses varies by VSCode version. POSITION_OF_ANSIBLE_EXPLAIN = 9 @@ -190,45 +182,19 @@ def user_is_auth(driver: WebDriver) -> bool: return bool(elts) -def _get_sso_credentials( - *, admin_login: bool, no_wca: bool, no_sub: bool -) -> tuple[str, str]: - """Return (username, password) based on the login scenario.""" - if no_sub and admin_login: - return NO_SUB_ADMIN, NO_SUB_PASSWORD - if no_sub: - return NO_SUB_USER, NO_SUB_PASSWORD - if no_wca and admin_login: - return NO_WCA_ADMIN, NO_WCA_PASSWORD - if no_wca: - return NO_WCA_USER, NO_WCA_PASSWORD - return LIGHTSPEED_USER, LIGHTSPEED_PASSWORD - - -def sso_auth_flow( # noqa: PLR0913 +def sso_auth_flow( driver: WebDriver, username: str = LIGHTSPEED_USER, password: str = LIGHTSPEED_PASSWORD, - *, - admin_login: bool = False, - no_wca: bool = False, - no_sub: bool = False, ) -> str: """Perform all the steps to log in with Red Hat SSO. - We have many parameters because of tests in test_login. - Args: driver: WebDriver instance username: Username for authentication password: Password for authentication - admin_login: Whether this is an admin login - no_wca: Whether to skip WCA - no_sub: Whether to skip subscription """ - user, password = _get_sso_credentials( - admin_login=admin_login, no_wca=no_wca, no_sub=no_sub - ) + user = username assert user assert password @@ -357,18 +323,16 @@ def vscode_login( driver: WebDriver, *, device_login: bool = True, - **kwargs: Any, ) -> None: """Go through the login process to ansible and vscode. Args: driver: WebDriver instance device_login: Whether to use device login flow (kept for compatibility) - **kwargs: Additional arguments passed to sso_auth_flow """ vscode_connect(driver) - sso_auth_flow(driver, **kwargs) + sso_auth_flow(driver) # switch back to vs-code driver.switch_to.window(driver.window_handles[0]) # user is now logged in, get a prediction @@ -696,74 +660,6 @@ def vscode_prediction( return prediction_preview -def vscode_trial_button( - driver: WebDriver, - file_name: str, - playbook: str, -) -> WebElement | None: - """Return the Trial button. - - Args: - driver: WebDriver instance - file_name: Name of the file to open - playbook: Playbook content to input - - Returns: - The Trial button element or None - """ - try: # in case explorer is already open - wait_displayed(driver, f"//span[text()='{file_name}']", timeout=1).click() - except ( - TimeoutException, - TimeOutError, - ElementClickInterceptedException, - ): # pragma: no cover - # go to explorer - explorer = wait_displayed( - driver, - "//a[contains(@aria-label, 'Explorer')]", - timeout=60, - ) - explorer.click() - # open the playbook - try: - wait_displayed(driver, f"//span[text()='{file_name}']", timeout=60).click() - except ElementClickInterceptedException: # pragma: no cover - ActionChains(driver).move_to_element(explorer).move_by_offset( - 0, - 50, - ).perform() - wait_displayed(driver, f"//span[text()='{file_name}']", timeout=60).click() - # click the text area to be able to input - clear_text(driver) - wait_displayed( - driver, - "//div[@class='view-lines monaco-mouse-cursor-text']", - timeout=60, - ).click() - lines = playbook.split("\n") - # input the content with low-level interactions - actions = ActionChains(driver) - for line in lines: - actions.send_keys(line) - actions.send_keys(Keys.ENTER) - actions.perform() - max_attempts = 4 - for n in range(max_attempts): - vscode_run_command_f1(driver, "Ansible Lightspeed: Inline suggestion trigger") - time.sleep(0.5) - try: - return wait_displayed( - driver, - "//a[contains(text(), 'Start a trial')]", - timeout=10, - ) - except TimeoutException: # pragma: no cover - if n == max_attempts - 1: - raise - return None - - def clear_text(driver: WebDriver) -> None: """Clear all the text in the vscode text code editor.