From a87ad750ead2a79d0b00cc2dface9b44c2fbf091 Mon Sep 17 00:00:00 2001 From: Jan Jasek Date: Wed, 27 Nov 2024 11:59:45 +0100 Subject: [PATCH] Allow configuring tests for different themes Allow configuring of locators/parts of the tests that are theme specific, using a config file. Change-Id: I7650ed4cff95674845c8613d424b76d296bf1a56 --- .../test/integration_tests/config.py | 15 +++++++++++++++ .../test/integration_tests/horizon.conf | 10 ++++++++++ openstack_dashboard/test/selenium/conftest.py | 18 ++++++++++-------- .../test/selenium/integration/conftest.py | 8 +++++--- .../test/selenium/integration/test_routers.py | 19 ++++++++++++------- .../selenium/integration/test_settings.py | 7 ++----- 6 files changed, 54 insertions(+), 23 deletions(-) diff --git a/openstack_dashboard/test/integration_tests/config.py b/openstack_dashboard/test/integration_tests/config.py index 20c1b16beb..11b39f0ab0 100644 --- a/openstack_dashboard/test/integration_tests/config.py +++ b/openstack_dashboard/test/integration_tests/config.py @@ -96,6 +96,9 @@ NetworkGroup = [ # can be changed as per available external network. default='public', help='The external network for a router creation.'), + cfg.StrOpt('subnet_name', + default='public-subnet', + help='Default public network subnet name'), ] AvailableServiceGroup = [ @@ -189,6 +192,16 @@ PluginGroup = [ help=('JSON string to define the page structure for the plugin')), ] +ThemeGroup = [ + cfg.StrOpt('project_name_xpath', + default='.//*[@class="context-project"]', + help='Default xpath for project name dropdown button'), + cfg.ListOpt('help_sequence', + default=['.//*[@class="dropdown user-menu"]', + './/*[normalize-space()="Help"]'], + help='Default steps for redirect to help URL'), +] + def _get_config_files(): conf_dir = os.path.join( @@ -216,6 +229,7 @@ def get_config(): cfg.CONF.register_opts(InstancesGroup, group="launch_instances") cfg.CONF.register_opts(PluginGroup, group="plugin") cfg.CONF.register_opts(VolumeGroup, group="volume") + cfg.CONF.register_opts(ThemeGroup, group="theme") return cfg.CONF @@ -233,4 +247,5 @@ def list_opts(): ("launch_instances", InstancesGroup), ("plugin", PluginGroup), ("volume", VolumeGroup), + ("theme", ThemeGroup), ] diff --git a/openstack_dashboard/test/integration_tests/horizon.conf b/openstack_dashboard/test/integration_tests/horizon.conf index 42409dabc3..d49d6217af 100644 --- a/openstack_dashboard/test/integration_tests/horizon.conf +++ b/openstack_dashboard/test/integration_tests/horizon.conf @@ -87,6 +87,8 @@ network_cidr=10.100.0.0/16 # Devstack default external network is 'public' but it can be changed # as per available external network. external_network=public +#public subnet name +subnet_name=public-subnet [service_available] # Whether is Neutron expected to be available (boolean value) @@ -108,3 +110,11 @@ flavor=m1.tiny volume_type=lvmdriver-1 volume_size=1 allow_delete_snapshot_before_volume=True + +#configuration for different theme +[theme] +#xpath for project name (dropdown button) +project_name_xpath=//*[@class="context-project"]//ancestor::ul + +#sequence for redirect to help URL +help_sequence=.//*[@class="dropdown user-menu"],.//*[normalize-space()="Help"] diff --git a/openstack_dashboard/test/selenium/conftest.py b/openstack_dashboard/test/selenium/conftest.py index 5b0a834121..43c82dfbaf 100644 --- a/openstack_dashboard/test/selenium/conftest.py +++ b/openstack_dashboard/test/selenium/conftest.py @@ -22,6 +22,7 @@ import xvfbwrapper from horizon.test import webdriver from openstack_dashboard.test.integration_tests import config as horizon_config +from openstack_dashboard.test.selenium import widgets STASH_FAILED = pytest.StashKey[bool]() @@ -44,6 +45,7 @@ class Session: config.identity.admin_home_project, ), } + self.project_name_xpath = config.theme.project_name_xpath self.logout_url = '/'.join(( config.dashboard.dashboard_url, 'auth', @@ -64,17 +66,17 @@ class Session: '.btn-primary') button.click() self.current_user = user - self.current_project = self.driver.find_element_by_class_name( - 'context-project').text + project_element = self.driver.find_element_by_xpath( + self.project_name_xpath) + self.current_project = project_element.text if self.current_project != project: - dropdown_project = self.driver.find_element_by_xpath( - '//*[@class="context-project"]//ancestor::ul') - dropdown_project.click() - selection = dropdown_project.find_element_by_xpath( + project_element.click() + selection = project_element.find_element_by_xpath( f'.//*[normalize-space()="{project}"]') selection.click() - self.current_project = self.driver.find_element_by_class_name( - 'context-project').text + widgets.get_and_dismiss_messages(self.driver) + self.current_project = self.driver.find_element_by_xpath( + self.project_name_xpath).text @pytest.fixture(scope='session') diff --git a/openstack_dashboard/test/selenium/integration/conftest.py b/openstack_dashboard/test/selenium/integration/conftest.py index 4171d6babe..20d08d5117 100644 --- a/openstack_dashboard/test/selenium/integration/conftest.py +++ b/openstack_dashboard/test/selenium/integration/conftest.py @@ -151,9 +151,11 @@ def new_default_test_subnet(new_default_test_network, openstack_admin): @pytest.fixture(scope='session') -def new_default_test_router(openstack_admin): - public_network = openstack_admin.network.find_network('public') - public_subnet = openstack_admin.network.find_subnet('public-subnet') +def new_default_test_router(openstack_admin, config): + public_network = openstack_admin.network.find_network( + config.network.external_network) + public_subnet = openstack_admin.network.find_subnet( + config.network.subnet_name) router = openstack_admin.network.post("/routers", json={ "router": { "name": "default_test_router", diff --git a/openstack_dashboard/test/selenium/integration/test_routers.py b/openstack_dashboard/test/selenium/integration/test_routers.py index 402e31f36d..6dc0cdc6e2 100644 --- a/openstack_dashboard/test/selenium/integration/test_routers.py +++ b/openstack_dashboard/test/selenium/integration/test_routers.py @@ -79,8 +79,10 @@ def new_interface(new_router_demo, new_network_demo, new_subnet_demo, @pytest.fixture -def new_router_with_gateway(new_router_demo, openstack_demo, openstack_admin): - network_id = openstack_admin.network.find_network('public').id +def new_router_with_gateway(new_router_demo, openstack_demo, openstack_admin, + config): + network_id = openstack_admin.network.find_network( + config.network.external_network).id openstack_demo.network.put( f"/routers/{new_router_demo.id}", @@ -103,7 +105,8 @@ def test_create_router_demo(login, driver, router_name, openstack_demo, driver.find_element_by_link_text("Create Router").click() router_form = driver.find_element_by_css_selector(".modal-dialog form") router_form.find_element_by_id("id_name").send_keys(router_name) - widgets.select_from_dropdown(router_form, "public") + widgets.select_from_dropdown(router_form, + config.network.external_network) router_form.find_element_by_css_selector( ".btn-primary[value='Create Router']").click() messages = widgets.get_and_dismiss_messages(driver) @@ -224,7 +227,7 @@ def test_router_set_gateway_demo(login, driver, new_router_demo, rows[0].find_element_by_css_selector(".data-table-action").click() gateway_form = driver.find_element_by_css_selector(".modal-dialog form") widgets.select_from_specific_dropdown_in_form( - gateway_form, 'id_network_id', 'public') + gateway_form, 'id_network_id', config.network.external_network) gateway_form.find_element_by_css_selector(".btn-primary").click() messages = widgets.get_and_dismiss_messages(driver) assert f"Success: Gateway interface is added" in messages @@ -233,7 +236,8 @@ def test_router_set_gateway_demo(login, driver, new_router_demo, f"?fields=id&fields=name&fields=" f"external_gateway_info").json()['router'] assert(router_sdk["external_gateway_info"]["network_id"] == - openstack_demo.network.find_network('public').id) + openstack_demo.network.find_network( + config.network.external_network).id) def test_router_clear_gateway_demo(login, driver, new_router_with_gateway, @@ -254,7 +258,8 @@ def test_router_clear_gateway_demo(login, driver, new_router_with_gateway, f"?fields=id&fields=name&fields=" f"external_gateway_info").json()['router'] assert(router_sdk["external_gateway_info"]["network_id"] == - openstack_demo.network.find_network('public').id) + openstack_demo.network.find_network( + config.network.external_network).id) rows[0].find_element_by_css_selector(".data-table-action").click() widgets.confirm_modal(driver) messages = widgets.get_and_dismiss_messages(driver) @@ -282,7 +287,7 @@ def test_create_router_admin(login, driver, router_name, openstack_admin, widgets.select_from_specific_dropdown_in_form( router_form, "id_tenant_id", "admin") widgets.select_from_specific_dropdown_in_form( - router_form, "id_external_network", "public") + router_form, "id_external_network", config.network.external_network) router_form.find_element_by_css_selector( ".btn-primary[value='Create Router']").click() messages = widgets.get_and_dismiss_messages(driver) diff --git a/openstack_dashboard/test/selenium/integration/test_settings.py b/openstack_dashboard/test/selenium/integration/test_settings.py index 4719dfd8b0..384a1b3f0c 100644 --- a/openstack_dashboard/test/selenium/integration/test_settings.py +++ b/openstack_dashboard/test/selenium/integration/test_settings.py @@ -14,8 +14,6 @@ from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait -from openstack_dashboard.test.selenium import widgets - def test_dashboard_help_redirection(login, driver, config): login('user') @@ -24,9 +22,8 @@ def test_dashboard_help_redirection(login, driver, config): 'settings', )) driver.get(url) - user_dropdown_menu = driver.find_element_by_css_selector( - '.nav.navbar-nav.navbar-right') - widgets.select_from_dropdown(user_dropdown_menu, "Help") + for step in config.theme.help_sequence: + driver.find_element_by_xpath(step).click() available_windows = driver.window_handles assert len(available_windows) == 2 driver.switch_to.window(available_windows[-1])