def kiali_client(): logger.debug('Creating kiali rest client') logger.debug('Kiali hostname: {}'.format(cfg.kiali.hostname)) _client = KialiExtendedClient(hostname=cfg.kiali.hostname, username=cfg.kiali.username, password=cfg.kiali.password, auth_type=cfg.kiali.auth_type, token=cfg.kiali.token, swagger_address=cfg.kiali.swagger_address) # update kiali version details _response = _client.get_response('getStatus') _status = _response['status'] cfg.kiali.version.core = _status['Kiali version'] cfg.kiali.version.console = _status['Kiali version'] # There is an issue to show video recordings when we use special chars in build details # https://github.com/zalando/zalenium/issues/572 # cfg.selenium.capabilities.zalenium.build = 'console:{}, core:{}:{}'.format( # cfg.kiali.version.console, # cfg.kiali.version.core, # _status['Kiali core commit hash']) cfg.selenium.capabilities.zalenium.build = '{}'.format( cfg.kiali.version.core) logger.info('Kiali versions:\n{}'.format(json.dumps(_response, indent=2))) return _client
def browser(kiali_client): selenium = _get_selenium() selenium.maximize_window() logger.debug('Launching kiali instance: {}'.format(cfg.kiali.hostname)) if cfg.kiali.auth_type == 'oauth': selenium.get( 'https://{}/#access_token={}&expires_in=86400&scope=user%3Afull&token_type=Bearer' .format(cfg.kiali.hostname, cfg.kiali.token)) else: selenium.get('https://{}'.format(cfg.kiali.hostname)) logger.debug('Launching kiali browser') # load KialiBrowser kiali_browser = KialiBrowser(selenium, logger=logger, kiali_versions={ 'core': cfg.kiali.version.core, 'console': cfg.kiali.version.console }) # ugly hack to pass browser object to zalenium fixtures # needs to remove this global assignment set_browser(kiali_browser) yield kiali_browser # update suite status on zalenium update_suite_status() kiali_browser.selenium.quit()
def test_menu(browser, kiali_client): # load root page page = RootPage(browser) # test available menus _response = kiali_client.get_response('getStatus') _products = _response['externalServices'] options_defined = [item.text for item in MainMenuEnum] if not _get_jaeger_url(_products): options_defined.remove(MainMenuEnum.DISTRIBUTED_TRACING.value) options_listed = page.main_menu.items logger.debug('menus[defined:{}, listed:{}]'.format(options_defined, options_listed)) assert is_equal(options_defined, options_listed), \ ('Menus mismatch: defined:{}, listed:{}'.format(options_defined, options_listed)) # navigate to menus for _menu in options_listed: if str(_menu) == MainMenuEnum.DISTRIBUTED_TRACING.text: assert _get_jaeger_url(_products) \ in page.main_menu.get_link(_menu).get_attribute('href') assert '_blank' == page.main_menu.get_link(_menu).get_attribute( 'target') continue logger.debug('Testing menu: {}'.format(_menu)) page.main_menu.select(_menu) assert page.main_menu.selected == _menu
def test_user_menu(browser): # load root page page = RootPage(browser) options_defined = [item.text for item in UserMenuEnum] options_listed = page.navbar.user_menu.options logger.debug('Menus[defined:{}, listed:{}]'.format(options_defined, options_listed)) assert is_equal(options_defined, options_listed), \ ('User menu mismatch: defined:{}, listed:{}'.format(options_defined, options_listed))
def delete_istio_config(self, name, namespace, kind, api_version): logger.debug('Deleting istio config: {}, from namespace: {}'.format( name, namespace)) try: self._istio_config(kind=kind, api_version=api_version).delete( name=name, namespace=namespace) except NotFoundError: pass
def test_help_menu(browser): # load root page page = RootPage(browser) # test available menus options_defined = [item.text for item in HelpMenuEnum] options_listed = page.navbar.help_menu.options logger.debug('help menus[defined:{}, listed:{}]'.format(options_defined, options_listed)) assert is_equal(options_defined, options_listed), \ ('Help menus mismatch: defined:{}, listed:{}'.format(options_defined, options_listed))
def test_invalid_login(browser): # load root page page = RootPage(browser, auto_login=False) # do login with invalid credentials _login = page.login(username='******', password='******') logger.debug('Login status:{}'.format(_login)) logger.debug('Notifications on screen:{}'.format(page.notifications.items)) assert not _login assert page.notifications.contains( type='danger', text='Unauthorized. Error in username or password')
def openshift_client(): if cfg.kiali.skip_oc: logger.debug('Skipping Openshift rest client because of cfg.kiali.skip_oc') # TODO Temporary solution as OC client does not support OCP4 return kiali_client() else: logger.debug('Creating Openshift rest client') _client = OpenshiftExtendedClient() logger.info('Openshift versions:\n{}'.format(json.dumps(_client.version, indent=2))) return _client
def test_refresh_interval(browser): # get page instance page = GraphPage(browser) # test options options_defined = [item.text for item in GraphRefreshInterval] interval = page.interval options_listed = interval.options logger.debug('Options[defined:{}, listed:{}]'.format( options_defined, options_listed)) assert is_equal(options_defined, options_listed), \ ('Options mismatch: defined:{}, listed:{}'.format(options_defined, options_listed))
def test_duration(browser): # get page instance page = GraphPage(browser) # test options options_defined = [item.text for item in TimeIntervalUIText] duration = page.duration options_listed = duration.options logger.debug('Options[defined:{}, listed:{}]'.format( options_defined, options_listed)) assert is_equal(options_defined, options_listed), \ ('Options mismatch: defined:{}, listed:{}'.format(options_defined, options_listed))
def test_login(browser): # load root page page = RootPage(browser, auto_login=False) # do login _login = page.login() logger.debug('Login status:{}'.format(_login)) assert _login # assert notifications logger.debug('Notifications on screen:{}'.format(page.notifications.items)) assert not page.notifications.contains(type=Notification.TYPE_DANGER) assert not page.notifications.contains(type=Notification.TYPE_WARNING)
def test_about(browser, kiali_client): # load root page page = RootPage(browser) _about = page.navbar.about() assert _about.application_logo versions_ui = _about.versions _about.close() _response = kiali_client.get_response('getStatus') _products = _response['externalServices'] if (any(d['name'] == ApplicationVersionEnum.ISTIO.text for d in _products)): version_enum = ApplicationVersionEnum else: version_enum = ApplicationVersionUpstreamEnum versions_defined = [item.text for item in version_enum] logger.debug('Versions information in UI:{}'.format(versions_ui)) logger.debug('Application version keys: defined:{}, available:{}'.format( versions_defined, versions_ui.keys())) assert is_equal(versions_defined, versions_ui.keys()) # compare each versions # get version details from REST API # kiali core version _core_rest = '{}{}'.format( _response['status']['Kiali version'], ' ({})'.format(_response['status']['Kiali commit hash']) if _response['status']['Kiali commit hash'] != 'unknown' else '') # skip in case of code coverage run where the version is not set correctly during the build if "ENABLE_CODE_COVERAGE" not in os.environ or os.environ[ "ENABLE_CODE_COVERAGE"] != "true": assert versions_ui[version_enum.KIALI_CORE.text] == _core_rest # versions mismatch between console on UI # TODO: check with manual test team and enable this # _console_rest = '{} ({})'.format( # _response['status']['Kiali version'], _response['status']['Kiali version']) # assert versions_ui[ApplicationVersionEnum.KIALI_UI.text] == _console_rest # test other product versions assert versions_ui[version_enum.ISTIO.text] == _get_version( _products, version_enum.ISTIO.text) # check Prometheus version assert versions_ui[version_enum.PROMETHEUS.text] == _get_version( _products, 'Prometheus') # check Kubernetes version assert versions_ui[version_enum.KUBERNETES.text] == _get_version( _products, 'Kubernetes')
def test_filter(browser): # get page instance page = GraphPage(browser) # test available filters options_defined = [item.text for item in GraphPageFilter] options_listed = page.filter.items logger.debug('options[defined:{}, listed:{}]'.format( options_defined, options_listed)) assert is_equal(options_defined, options_listed), \ ('Options mismatch: defined:{}, listed:{}'.format(options_defined, options_listed)) # enable disable each filter for filter_name in options_listed: _filter_test(page, filter_name)
def test_invalid_login(browser): # load root page page = RootPage(browser, auto_login=False) # do login with invalid credentials _login = page.login(username='******', password='******') logger.debug('Login status:{}'.format(_login)) logger.debug('Notifications on screen:{}'.format(page.notifications.items)) assert not _login assert page.notifications.contains( _type='danger', text='Unauthorized. ' 'The provided credentials are not valid to access Kiali. ' 'Please check your credentials and try again.')
def create_istio_config(self, body, namespace, kind, api_version): """Creates Istio Config. Args: body: config body namespaces: namespace where Config is located kind: type of the Config api_version: Config api version (not used) """ logger.debug('Creating istio config: {}, from namespace: {}'.format( body['metadata']['name'], namespace)) return self.post_response('istioConfigCreate', namespace=namespace, object_type=ISTIO_CONFIG_TYPES[kind], data=body)
def test_menu(browser): # load root page page = RootPage(browser) # test available menus options_defined = [item.text for item in MainMenuEnum] options_listed = page.main_menu.items logger.debug('menus[defined:{}, listed:{}]'.format(options_defined, options_listed)) assert is_equal(options_defined, options_listed), \ ('Menus mismatch: defined:{}, listed:{}'.format(options_defined, options_listed)) # navigate to menus for _menu in options_listed: logger.debug('Testing menu: {}'.format(_menu)) page.main_menu.select(_menu) assert page.main_menu.selected == _menu
def delete_istio_config(self, name, namespace, kind, api_version): """Deletes Istio Config. Args: name: config name namespaces: namespace where Config is located kind: type of the Config api_version: Config api version (not used) """ logger.debug('Deleting istio config: {}, from namespace: {}'.format( name, namespace)) return self.delete_response('istioConfigDelete', namespace=namespace, object_type=ISTIO_CONFIG_TYPES[kind], object=name)
def _get_driver(capabilities): logger.debug('Creating web driver') start_time = datetime.now() # set resolve_ip to false to make it work in cases when remote driver is running in OpenShift command_executor = RemoteConnection(cfg.selenium.web_driver, resolve_ip=False) # increase the timeout because we are waiting for new pod to be created which takes some time command_executor.set_timeout(120) driver = webdriver.Remote(command_executor, desired_capabilities=capabilities) # reset the timeout to default, only driver creation is taking so much time command_executor.reset_timeout() _delta = datetime.now() - start_time logger.debug('Web driver created successfully. Time taken: {} ms'.format( int(_delta.total_seconds() * 1000))) return driver
def _pick_namespace(name): """ Checks if required namespace exists, if not it picks the default namespace to run test against and logs warning. :param name: name of required namespace :returns: name of required namespace if exists, default namespace otherwise """ if openshift_client.namespace_exists(name): logger.debug('{} namespace is available'.format(name)) return name else: logger.warning( 'This tests requires {} namespace to be available to run the test safely \ in parallel!!! Using default namespace {}. Ignore if you run tests sequentially.' .format(name, DEFAULT_BOOKINFO_NAMESPACE)) return DEFAULT_BOOKINFO_NAMESPACE
def load(self, force_load=False, force_refresh=False): logger.debug('Loading page') # if auto login enabled, do login. else do logout # TODO: SWSQE-992 this was throwing selenium.common.exceptions.WebDriverException: # Message: unknown error: failed to parse value of getElementRegion # login function is not working anyway now so disabling it to get rid of that failure # if self._auto_login: # if login page displayed, do login # self.login() # else: # self.logout() # load particular page, only if PAGE_MENU is supplied and is not already displayed if self.PAGE_MENU is not None and \ (self.main_menu.selected != self.PAGE_MENU or (self.PAGE_MENU != MENU.OVERVIEW.text and not self.namespace_filter.is_available) or force_load): self.main_menu.select(self.PAGE_MENU) if force_refresh: self.page_refresh() wait_to_spinner_disappear(self.browser) wait_displayed(self)
def apply_filters(self, filters, force_clear_all=True): """ Apply supplied filter in to UI and assert with supplied and applied filters Parameters ---------- filters : list A list for filter. filter should be a dict. filter = {'name': 'Namespace', 'value': 'bookinfo'} Take filter name from pre defined enum force_clear_all : boolean Default True. If this value is True, all existing applied filters will be removed. otherwise, will be adjusted with pre filter. on both case final outcome will be same. """ _pre_filters = [] # clear all filters if force_clear_all: self.page.filter.clear_all() assert len(self.page.filter.active_filters) == 0 else: _pre_filters.extend(self.page.filter.active_filters) # apply filter for _filter in filters: if _filter not in _pre_filters: self.page.filter.apply(filter_name=_filter['name'], value=_filter['value']) if _filter in _pre_filters: _pre_filters.remove(_filter) # remove filters not in list for _filter in _pre_filters: self.page.filter.remove(filter_name=_filter['name'], value=_filter['value']) # validate applied filters _active_filters = self.page.filter.active_filters logger.debug('Filters[applied:{}, active:{}]'.format( filters, _active_filters)) assert is_equal(filters, _active_filters)
def browser(kiali_client): selenium = _get_selenium() selenium.maximize_window() logger.debug('Launching kiali instance: {}'.format(cfg.kiali.hostname)) selenium.get('http://{}:{}@{}'.format(cfg.kiali.username, cfg.kiali.password, cfg.kiali.hostname)) # load KialiBrowser kiali_browser = KialiBrowser(selenium, logger=logger, kiali_versions={ 'core': cfg.kiali.version.core, 'console': cfg.kiali.version.console }) # ugly hack to pass browser object to zalenium fixtures # needs to remove this global assignment set_browser(kiali_browser) yield kiali_browser # update suite status on zalenium update_suite_status() kiali_browser.selenium.quit()
def assert_pagination_feature(self): pagination = self.page.pagination # test options options_defined = [item.value for item in PaginationPerPage] options_listed = pagination.items_per_page_options logger.debug('options[defined:{}, listed:{}]'.format( options_defined, options_listed)) assert is_equal(options_defined, options_listed), \ ('Options mismatch: defined:{}, listed:{}'.format(options_defined, options_listed)) # test page next, previous, first, last, to page total_pages = pagination.total_pages if total_pages > 1: # last page pagination.move_to_last_page() assert pagination.current_page == total_pages # first page pagination.move_to_first_page() assert pagination.current_page == 1 # next page pagination.move_to_next_page() assert pagination.current_page == 2 # previous page pagination.move_to_previous_page() assert pagination.current_page == 1 # to page pagination.move_to_page(2) assert pagination.current_page == 2 # navigate to all pages for to_page in range(1, total_pages + 1): pagination.move_to_page(to_page) assert pagination.current_page == to_page # test items per page and options for per_page in options_listed: if pagination.total_items > per_page: pagination.set_items_per_page(per_page) assert len(self.page.content.items) == per_page assert pagination.items_per_page == per_page # test total items assert pagination.total_items == len(self.page.content.all_items)
def _get_driver(capabilities): logger.debug('Creating web driver') start_time = datetime.now() # set resolve_ip to false to make it work in cases when remote driver is running in OpenShift # https://github.com/ddavison/selenium-openshift-templates/issues/6 command_executor = RemoteConnection(cfg.selenium.web_driver, resolve_ip=False) # increase the timeout because we are waiting for new pod to be created which takes some time command_executor.set_timeout(120) # using keep_alive=True which should save some connections # https://github.com/SeleniumHQ/selenium/issues/5758 # and https://github.com/seleniumhq/selenium/issues/3457 driver = webdriver.Remote(command_executor, desired_capabilities=capabilities, options=_get_browser_options(), keep_alive=True) # reset the timeout to default, only driver creation is taking so much time command_executor.reset_timeout() _delta = datetime.now() - start_time logger.debug('Web driver created successfully. Time taken: {} ms'.format( int(_delta.total_seconds() * 1000))) return driver
def test_about(browser, kiali_client): # load root page page = RootPage(browser) _about = page.navbar.about() assert _about.application_name == 'Kiali' versions_ui = _about.versions logger.debug('Versions information in UI:{}'.format(versions_ui)) versions_defined = [item.text for item in ApplicationVersionEnum] logger.debug('Application version keys: defined:{}, available:{}'.format( versions_defined, versions_ui.keys())) assert is_equal(versions_defined, versions_ui.keys()) # compare each versions # get version details from REST API _response = kiali_client.status() # kiali core version _core_rest = '{} ({})'.format( _response['status']['Kiali core version'], _response['status']['Kiali core commit hash']) assert versions_ui[ApplicationVersionEnum.KIALI_CORE.text] == _core_rest # versions mismatch between console on UI # TODO: check with manual test team and enable this # _console_rest = '{} ({})'.format( # _response['status']['Kiali core version'], _response['status']['Kiali console version']) # assert versions_ui[ApplicationVersionEnum.KIALI_UI.text] == _console_rest # test other product versions _products = _response['externalServices'] # check istio version assert versions_ui[ApplicationVersionEnum.ISTIO.text] == _get_version( _products, 'Istio') # check Prometheus version assert versions_ui[ApplicationVersionEnum.PROMETHEUS.text] == _get_version( _products, 'Prometheus') # check Kubernetes version assert versions_ui[ApplicationVersionEnum.KUBERNETES.text] == _get_version( _products, 'Kubernetes')
def assert_namespaces(self): namespaces_ui = self._namespaces_ui() namespaces_rest = self.kiali_client.namespace_list() namespaces_oc = self.openshift_client.namespace_list() logger.debug('Namespaces UI:{}'.format(namespaces_ui)) logger.debug('Namespaces REST:{}'.format(namespaces_rest)) logger.debug('Namespaces OC:{}'.format(namespaces_oc)) assert is_equal(namespaces_ui, namespaces_rest) assert is_equal(namespaces_rest, namespaces_oc)
def assert_filter_feature_random(self): # clear filters if any # TODO: do we need to fail the test if we have filter defined before test? logger.debug('Filters before test:{}'.format( self.page.filter.active_filters)) self.page.filter.clear_all() # get namespaces namespaces_ui = self._namespaces_ui() # apply a namespace filter # generate random filters list _defined_filters = [] # random namespace filters assert len(namespaces_ui) > 0 if len(namespaces_ui) > 3: _random_namespaces = random.sample(namespaces_ui, 3) else: _random_namespaces = namespaces_ui # create filters for _selected_namespace in _random_namespaces: _defined_filters.append({ 'name': self.FILTER_ENUM.NAMESPACE.text, 'value': _selected_namespace }) # add additional filters logger.debug('Adding additional filters') _defined_filters.extend(self.get_additional_filters(_defined_filters)) logger.debug('Defined filters with additional filters:{}'.format( _defined_filters)) # apply filters test _applied_filters = [] for _defined_filter in _defined_filters: # add it in to applied list _applied_filters.append(_defined_filter) # apply filter and check the contents self.assert_all_items(filters=_applied_filters, force_clear_all=False) # remove filters test for _defined_filter in _defined_filters: # remove it from our list _applied_filters.remove(_defined_filter) # apply filter and check the contents self.assert_all_items(filters=_applied_filters, force_clear_all=False) # test remove all if len(_applied_filters) == 2: self.assert_all_items(filters=[], force_clear_all=True) break
def get_additional_filters(self, current_filters): logger.debug('Current filters:{}'.format(current_filters)) # get services of a namespace _namespace = current_filters[0]['value'] logger.debug( 'Running Services REST query for namespace:{}'.format(_namespace)) _services = self.kiali_client.service_list(namespaces=[_namespace]) logger.debug('Query response, Namespace:{}, Services:{}'.format( _namespace, _services)) # if we have a service, select a service randomly and return it if len(_services) > 0: _random_service = random.choice(_services) return [{ 'name': self.FILTER_ENUM.SERVICE_NAME.text, 'value': _random_service.name }] return []
def assert_all_items(self, filters, force_clear_all=True): logger.debug('Filters:{}'.format(filters)) # apply filters self.apply_filters(filters=filters, force_clear_all=force_clear_all) # get rules from ui config_list_ui = self.page.content.all_items logger.debug('Istio config list UI:{}]'.format(config_list_ui)) # get rules from rest api config_list_rest = self.kiali_client.istio_config_list(filters=filters) logger.debug('Istio config list REST:{}]'.format(config_list_rest)) # compare both results assert len(config_list_ui) == len(config_list_rest) for config_ui in config_list_ui: found = False for config_rest in config_list_rest: if config_ui.is_equal(config_rest, advanced_check=False): found = True break assert found, '{} not found in REST'.format(config_rest)
def get_additional_filters(self, current_filters): logger.debug('Current filters:{}'.format(current_filters)) # get rules of a namespace _namespace = current_filters[0]['value'] logger.debug( 'Running Rules REST query for namespace:{}'.format(_namespace)) _istio_config_list = self.kiali_client.istio_config_list( filters=[{ 'name': self.FILTER_ENUM.NAMESPACE.text, 'value': _namespace }]) logger.debug( 'Query response, Namespace:{}, Istio config list:{}'.format( _namespace, _istio_config_list)) # if we have a config, select a config randomly and return it if len(_istio_config_list) > 0: _random_config = random.choice(_istio_config_list) return [{ 'name': self.FILTER_ENUM.ISTIO_NAME.text, 'value': _random_config.name }] return []