def wait_history_row_with_value(self, row: WebElement, value: str): """Wait for value in History row""" def _assert_value(): assert self.get_history_in_row( row)[0] == value, "History row should contain old value" wait_until_step_succeeds(_assert_value, timeout=4, period=0.5)
def send_text_to_element( self, element: Union[Locator, WebElement], text: str, clean_input: bool = True, timeout: Optional[int] = None ): """ Writes text to input element found by locator If value of input before and after is the same, then retries to send keys again, because sometimes text doesn't appear in input :param locator: Locator of element to write into (should be input) :param text: Text to use in .send_keys method and it's also a expected_value :param clean_input: Clear input before saving element or not :param timeout: Timeout on finding element """ def _send_keys_and_check(): if clean_input: self.clear_by_keys(element) input_element = self.find_element(element, timeout) if isinstance(element, Locator) else element input_element.send_keys(text) assert ( actual_value := input_element.get_property('value') ) == text, f'Value of input {element.name if isinstance(element, Locator) else element.text} expected to be "{text}", but "{actual_value}" was found' wait_until_step_succeeds(_send_keys_and_check, period=0.5, timeout=1.5)
def wait_file_is_presented( filename: str, app_fs: ADCMTest, dirname: os.PathLike, timeout: Union[int, float] = 30, period: Union[int, float] = 1, ): """Checks if file is presented in directory""" if app_fs.selenoid['host']: dir_url = f'http://{app_fs.selenoid["host"]}:{app_fs.selenoid["port"]}/download/{app_fs.driver.session_id}' file_url = f'{dir_url}/{filename}' def _check_file_is_presented(): response = requests.get(file_url) assert ( response.status_code < 400 ), f'Request for file ended with {response.status_code}, file request text: {response.text}.' else: def _check_file_is_presented(): assert filename in os.listdir( dirname), f'File {filename} not found in {dirname}' wait_until_step_succeeds(_check_file_is_presented, timeout=timeout, period=period)
def wait_success_job_amount_from_header(self, expected_job_amount: int): """Wait for success job amount to be as expected""" def _wait_job(): assert ( int(self.get_success_job_amount_from_header()) == expected_job_amount ), f"Should be {expected_job_amount} tasks in popup header" wait_until_step_succeeds(_wait_job, period=1, timeout=70)
def get_host_row(self, row_num: int = 0) -> WebElement: """Get host information from row""" def _table_has_enough_rows(): assert_enough_rows(row_num, self.table.row_count) wait_until_step_succeeds(_table_has_enough_rows, timeout=5, period=0.1) rows = self.table.get_all_rows() assert_enough_rows(row_num, len(rows)) return rows[row_num]
def check_username(self, expected_username: str): """Wait for username to be what it is expected on opened profile page""" def _check_username_on_profile_page(): assert ( username := self.get_username() ) == expected_username, f'Expected username is {expected_username}, got {username} instead' wait_until_step_succeeds(_check_username_on_profile_page, timeout=5, period=0.5)
def get_login_warning_text(self, timeout: int = None) -> str: """Get warning text on login page""" def _get_text(): assert self.find_element( LoginPageLocators.login_warning).text != "" wait_until_step_succeeds(_get_text, period=1, timeout=timeout or self.default_loc_timeout) return self.find_element(LoginPageLocators.login_warning).text
def wait_rows_collapsed(self): """Wait when status info is visible or hidden.""" rows_before = len(self.get_all_rows()) yield def _wait_collapsed(): assert rows_before != len( self.get_all_rows()), "Status info rows has not been changed" wait_until_step_succeeds(_wait_collapsed, period=1, timeout=5)
def get_single_job_row_from_popup(self, row_num: int = 0) -> WebElement: """Get single job row from *opened* popup""" def _popup_table_has_enough_rows(): assert_enough_rows(row_num, self.popup_jobs_row_count) with allure.step('Check popup table has enough rows'): wait_until_step_succeeds(_popup_table_has_enough_rows, timeout=5, period=0.1) rows = self.get_job_rows_from_popup() assert_enough_rows(row_num, len(rows)) return rows[row_num]
def clear_by_keys(self, element: Union[Locator, WebElement]) -> None: """Clears element value by keyboard.""" def _clear(): locator_before = element if isinstance(element, WebElement) else self.find_element(element) locator_before.send_keys(Keys.CONTROL + "a") locator_before.send_keys(Keys.BACK_SPACE) locator_after = element if isinstance(element, WebElement) else self.find_element(element) assert locator_after.text == "" wait_until_step_succeeds(_clear, period=0.5, timeout=self.default_loc_timeout)
def wait_page_is_opened(self, timeout: int = None): """Wait for current page to be opened""" timeout = timeout or self.default_page_timeout def _assert_page_is_opened(): assert self.path in self.driver.current_url, f'Page is not opened at path {self.path} in {timeout}' page_name = self.__class__.__name__.replace('Page', '') with allure.step(f'Wait page {page_name} is opened'): wait_until_step_succeeds(_assert_page_is_opened, period=0.5, timeout=timeout) self.wait_element_hide(CommonToolbarLocators.progress_bar)
def check_fqdn_equal_to(self, fqdn: str): """Check if fqdn on page is equal to given one""" def _check(element): real_fqdn = element.text assert real_fqdn == fqdn, f'Expected FQDN is {fqdn}, but FQDN in menu is {real_fqdn}' fqdn_element = self.find_element(ObjectPageLocators.title) wait_until_step_succeeds(_check, timeout=5, period=0.1, element=fqdn_element)
def wait_rows_change(self): """Wait changing rows amount""" current_amount = len(self.get_all_rows()) yield def _wait_scroll(): assert len(self.get_all_rows( )) != current_amount, "Amount of rows on the page hasn't changed" self.wait_element_hide(CommonToolbarLocators.progress_bar) wait_until_step_succeeds(_wait_scroll, period=1, timeout=10)
def wait_component_state_change(self, row: WebElement): """Wait for component state to change""" state_before = self.get_component_state_from_row(row) yield def _wait_state(): state_after = self.get_component_state_from_row(row) assert state_after != state_before assert state_after != self.table.LOADING_STATE_TEXT wait_until_step_succeeds(_wait_state, period=1, timeout=self.default_loc_timeout)
def wait_group_changed(self, group_name: str): """Wait while group is opened or closed""" group_state_before = self.find_element( self.locators.group_btn(group_name)).get_attribute("class") yield def check_group_clicked(): group_state_after = self.find_element( self.locators.group_btn(group_name)).get_attribute("class") assert group_state_before != group_state_after, "Group has not changed" wait_until_step_succeeds(check_group_clicked, period=1, timeout=10)
def wait_provider_state_change(self, row: WebElement): """Wait for provider state change""" state_before = self.get_provider_info_from_row(row).state yield def _wait_state(): state_after = self.get_provider_info_from_row(row).state assert state_after != state_before assert state_after != self.table.LOADING_STATE_TEXT wait_until_step_succeeds(_wait_state, period=1, timeout=self.default_loc_timeout)
def assert_host_bonded_to_cluster(self, row_num: int, cluster_name: str): """Assert host in row is assigned to cluster""" def _check_host_cluster(page: HostListPage, row: WebElement): real_cluster = page.find_child( row, HostListLocators.HostTable.HostRow.cluster).text assert real_cluster == cluster_name host_row = self.table.get_row(row_num) wait_until_step_succeeds(_check_host_cluster, timeout=5, period=0.1, page=self, row=host_row)
def assert_host_state(self, row_num: int, state: str): """Assert host in row has state given state""" def _check_host_state(page: HostListPage, row: WebElement): real_state = page.find_child( row, HostListLocators.HostTable.HostRow.state).text assert real_state == state host_row = self.table.get_row(row_num) wait_until_step_succeeds(_check_host_state, timeout=10, period=0.5, page=self, row=host_row)
def expect_rows_amount_change(get_all_rows: Callable[[], Sized]): """Waits for row count to be changed""" current_amount = len(get_all_rows()) yield @ignore_flaky_errors def _check_rows_amount_is_changed(): assert len(get_all_rows( )) != current_amount, "Amount of rows on the page hasn't changed" wait_until_step_succeeds(_check_rows_amount_is_changed, period=1, timeout=10)
def _wait_and_get_action_on_host(host: Host, display_name: str) -> Action: """Wait until action is presented on host (wait for host action)""" def _wait_for_action_to_be_presented(): try: host.action(display_name=display_name) except ObjectNotFound: assert ( # noqa: PT015 False ), f'Action "{display_name}" is not presented on host {host.fqdn}. Actions: {host.action_list()}' utils.wait_until_step_succeeds(_wait_for_action_to_be_presented, period=0.1, timeout=10) return host.action(display_name=display_name)
def open(self, timeout: int = None): """Open page by its url and path.""" url = self.base_url + self.path def _open_page(): if self.driver.current_url != url: with allure.step(f"Open {url}"): self.driver.get(url) assert self.path in self.driver.current_url, ( "Page URL didn't change. " f'Actual URL: {self.driver.current_url}. Expected URL: {url}.' ) wait_until_step_succeeds(_open_page, period=0.5, timeout=timeout or self.default_page_timeout) return self
def expand_or_close_group(self, group_name: str, expand: bool = True): """Click on group with given title""" group = self.find_element(self.locators.group_btn(group_name)) def click_on_group(): with self.wait_group_changed(group_name): self.find_child(group, CommonLocators.mat_slide_toggle).click() is_expand = "expanded" in self.find_element( self.locators.group_btn(group_name)).get_attribute("class") assert ( is_expand if expand else not is_expand ), f"Group {group_name} should{' ' if expand else ' not '}be expanded" wait_until_step_succeeds(click_on_group, period=1, timeout=10)
def wait_service_state_change(self, row: WebElement): """Wait for service state to change""" state_before = self.get_service_state_from_row(row) yield def _wait_state(): state_after = self.get_service_state_from_row(row) assert state_after != state_before, f"State should not be equal {state_before}" assert ( state_after != self.table.LOADING_STATE_TEXT ), f"State should not be equal {self.table.LOADING_STATE_TEXT}" wait_until_step_succeeds(_wait_state, period=1, timeout=self.default_loc_timeout)
def click_on_group(self, title: str): """Click on group with given title""" def _is_group_expanded(group: WebElement): return "expanded" in group.get_attribute("class") def _click_group(): group = self.find_element(self.locators.group_btn(title)) is_expanded = _is_group_expanded(group) group.click() assert ( _is_group_expanded( self.find_element( self.locators.group_btn(title))) != is_expanded ), f"Group should be{'' if is_expanded else ' not '}expanded" wait_until_step_succeeds(_click_group, period=1, timeout=10)
def assert_input_value_is(self, expected_value: str, display_name: str, *, is_password: bool = False): """ Assert that value in field is expected_value (using retries) :param expected_value: Value expected to be in input field :param display_name: Config field display name :param is_password: Is field password/confirmation """ def _assert_value(): input_value = self.get_input_value( row=self.get_config_row(display_name), is_password=is_password) assert expected_value == input_value, f'Expected value was {expected_value} but presented is {input_value}' wait_until_step_succeeds(_assert_value, timeout=4, period=0.5)
def wait_rows_change(self, expected_rows_amount: Optional[int] = None): """Wait changing rows amount.""" amount_before = len(self.get_all_config_rows()) yield def _wait_changing_rows_amount(): amount_after = len(self.get_all_config_rows()) assert amount_after != amount_before, "Amount of rows on the page hasn't changed" if expected_rows_amount: assert ( amount_after == expected_rows_amount ), f"Amount of rows on the page should be {expected_rows_amount}" wait_until_step_succeeds(_wait_changing_rows_amount, period=1, timeout=10)
def test_check_host_lock_during_operations(forth_p: Provider): """Test scenario: 1. Create provider 2. Create host first host on provider 3. Run job that creates the second host on provider 4. Wait until second host will be created. 5. Check that both host is locked 6. Wait for job to be finished without errors 7. Check that both hosts is free 8. Run remove action on one of hosts 9. Check that host under action is locked, while other host is free 10. Wait for job to be finished without errors 11. Check that remaining host is free. """ with allure.step('Create host first host on provider'): forth_p.action(name="create_host").run(config_diff={'fqdn': "forth_one"}).try_wait() with allure.step('Run job that creates the second host on provider'): job = forth_p.action(name="create_host").run(config={'fqdn': "forth_two", 'sleep': 2}) with allure.step('Wait until second host will be created'): wait_until_step_succeeds(_assert_that_object_exists, period=0.5, get_object_func=forth_p.host, fqdn="forth_two") forth_two_h = forth_p.host(fqdn="forth_two") forth_one_h = forth_p.host(fqdn='forth_one') with allure.step('Check that both host has is locked'): assert forth_one_h.locked is True assert forth_two_h.locked is True with allure.step('Wait for job to be finished without errors'): job.try_wait() with allure.step('Check that both hosts is free'): forth_one_h.reread() forth_two_h.reread() assert forth_one_h.locked is False assert forth_two_h.locked is False with allure.step('Run remove action on one of hosts'): job = forth_one_h.action(name="remove_host").run(config={"sleep": 2}) with allure.step('Check that host under action is locked, while other host is free'): forth_one_h.reread() forth_two_h.reread() assert forth_one_h.locked is True assert forth_two_h.locked is False with allure.step('Wait for job to be finished without errors'): job.try_wait() with allure.step('Check that remaining host is free'): forth_two_h.reread() assert forth_two_h.locked is False
def _with_items_added(self, row: WebElement): """Wait for new items to appear after 'add new' button is clicked""" before = len( self.find_children(row, CommonConfigMenu.ConfigRow.value, timeout=2)) yield def check_new_item_appeared(): assert ( len( self.find_children(row, CommonConfigMenu.ConfigRow.value, timeout=1)) > before ), f'New item should appear in {row}, but there are still {before} rows' wait_until_step_succeeds(check_new_item_appeared, timeout=10, period=1)
def test_upgrade_adcm( app_fs: ADCMTest, sdk_client_fs: ADCMClient, adcm_api_credentials: dict, adcm_image_tags: Tuple[str, str], ): """ Login to ADCM (previous version) Upgrade ADCM Check messages about ADCM upgrade Check that user is still logged in (open different tabs) """ credentials = {**adcm_api_credentials} credentials['username'] = credentials.pop('user') with allure.step('Login to ADCM with UI'): login_page = LoginPage(app_fs.driver, app_fs.adcm.url).open() login_page.login_user(**credentials) intro_page = PreviousAdminIntroPage(login_page.driver, login_page.base_url) intro_page.wait_page_is_opened() intro_page.wait_config_loaded() with allure.step('Start ADCM upgrade with client'): upgrade_thread = threading.Thread(target=upgrade_adcm_version, args=(app_fs.adcm, sdk_client_fs, adcm_api_credentials, adcm_image_tags)) upgrade_thread.start() with allure.step('Check update popup messages are present'): for message in ( 'Connection lost. Recovery attempt.', 'No connection to back-end. Check your internet connection.', 'New version available. Page has been refreshed.', ): with allure.step(f'Check message "{message}" is presented'): # TODO one day make first wait a long one, others shorter like 90, 30, 30 or smt like that wait_until_step_succeeds(wait_info_popup_contains, page=intro_page, text=message, timeout=77, period=0.3) with allure.step('Wait for upgrade to finish'): upgrade_thread.join(timeout=60) open_different_tabs(intro_page)
def wait_element_attribute( self, locator: Locator, attribute: str, expected_value: str, exact_match: bool = True, timeout: int = 5, ): """ Wait for element to has locator's attribute equals to `expected_value` If exact match is False then __contains__ is used """ comparator = '__eq__' if exact_match else '__contains__' def _assert_attribute_value(): actual_value = self.find_element(locator).get_attribute(attribute) assert getattr(actual_value, comparator)(expected_value), ( f'Attribute {attribute} of element "{locator}" ' f'should be/has "{expected_value}", but "{actual_value}" was found' ) wait_until_step_succeeds(_assert_attribute_value, period=0.5, timeout=timeout)