def set_style(self, element, style, value, is_important=True): log_step(f"Set style {style}={value} on {element}") if is_important: script = f"arguments[0].style.setProperty('{style}', '{value}', 'important')" else: script = f"arguments[0].style.setProperty('{style}', '{value}')" self.execute_js(script, self._match_first_or_fail(element))
def press_key(self, element, *chars): """ Нажимает кнопки. Чтобы ввести символы с модификатором (ctrl, alt, shift, meta), передай кортеж у которого первый элемент модификатор, а второй текст. Args: element (Element): Элемент, куда посылать нажатия *chars (str|tuple): Что вводить. Может быть строкой или кортежем в модификатором Examples: Дано: поле, в которое введён текст ``old``:\n ``<input id="input" value="old" />`` >>> from selenium.webdriver.common.keys import Keys >>> field = Find("#input") >>> browser.press_key(field, "A") oldA >>> browser.press_key(field, ("ctrl", "a"), "new") new >>> browser.press_key(field, ("shift", "333"), "2", "x") old###2x >>> browser.press_key(field, Keys.BACKSPACE) ol """ log_step(f"Press keys {chars} on {element}") el = self._match_first_or_fail(element) for char in chars: el.send_keys(*self._convert_key_modifier(char))
def see_number_of_elements(self, element, expected): """ Проверяет, что на странице определённое кол-во элементов. Args: element (Element): Элемент expected (int|tuple): Ожидаемое кол-во Returns: None Raises: AssertionError Examples: >>> browser.see_number_of_elements( E('tr'), 10 ) >>> browser.see_number_of_elements( E('tr'), (4, 6) ) # Между 4 и 6, включительно """ log_step(f"See number of elements {element}, {expected}") count = len(self._match_visible(element)) if isinstance(expected, tuple): a, b = expected assert_that(a <= count <= b, is_(True), f'Number of elements expected to be in range {expected}, but was {count}') else: assert_that(count, equal_to(expected), f'Number of elements expected to be {expected}, but was {count}')
def grab_page_html(self): """ Возвращает html всей страницы. Returns: str: html """ log_step("Grab page html") return self.get_driver().page_source
def attach_file(self, element, file_name): log_step(f"Attach file {file_name}") file_path = session.data_dir.joinpath(file_name) if not Path.exists(file_path): raise IOError(f"File does not exist: {file_path}") self.get_driver().file_detector = LocalFileDetector() self.fill_field(element, str(file_path))
def get_screenshot_binary(self): """ Возвращает скриншот в бинарном формате. Returns: bytes """ log_step(f"Get screenshot as png") return self.get_driver().get_screenshot_as_png()
def grab_html_from(self, element): """ Возвращает html элемента. Returns: str: html """ log_step(f"Grab html from {element}") el = self._match_first_or_fail(element) return el.get_attribute('outerHTML')
def grab_console_log(self): ''' Получить лог браузерной консоли. Буффер очищается после каждого запроса. Требует сapability ``loggingPrefs: { browser: 'INFO' }``. Returns: list[str]: список строк ''' log_step("Grab browser console log") return self.get_driver().get_log('browser')
def move_mouse_over(self, element): """ Передвигает курсор в центр элемента Args: element (Element): элемент """ log_step(f"Move mouse over {element}") el = self._match_first_or_fail(element) ActionChains(self.get_driver()).move_to_element(el).perform()
def scroll_into_view(self, element, scroll_into_view_options={"block": "center"}): """ Скролит страницу к элементу Args: element (Element): Элемент scroll_into_view_options (dict, optional): Параметры, по умолчанию {'block': 'center'} https://developer.mozilla.org/ru/docs/Web/API/Element/scrollIntoView """ log_step("Scroll into view") el = self._match_first_or_fail(element) self.execute_js(f"arguments[0].scrollIntoView({json.dumps(scroll_into_view_options)})", el)
def close_window(self): """ Закрывает текущее окно и переключается в предыдущее. Returns: window handle """ log_step("Close window") prev_window = self.get_relative_window_handle(-1) self.get_driver().close() self.get_driver().switch_to.window(prev_window) return prev_window
def open_url(self, url): """ Переходит по абсолютному URL. Args: url (str): URL Examples: >>> browser.open_url("https://google.com") """ log_step(f"Open URL {url}") self.get_driver().get(url)
def click(self, element): """ Кликает по элементу. Args: element (Element): Элемент Examples: >>> browser.click(Element("#logout")) """ log_step(f"Click {element}") self._match_first_or_fail(element).click()
def clear_field(self, input_element): """ Очищает поле. Args: input_element (Element): Поле ввода Examples: >>> browser.clear_field(Element("#input")) """ log_step(f"Clear field {input_element}") el = self._match_first_or_fail(input_element) el.clear()
def sleep(self, secs): """ Просто ждёт ``secs`` секунд. Args: secs (float): Сколько секунд спать Raises: Exception: Если передали больше 1000 сек. """ log_step(f"Sleep {secs}") if secs >= 1000: raise Exception("Waiting for more then 1000 seconds: 16.6667 mins") time.sleep(secs)
def switch_to_prev_window(self, offset=1): """ Переключается в предыдущее окно. Args: offset (int, optional): По умолчанию 1 Returns: window handle """ log_step("Switching to prev window") next_window = self.get_relative_window_handle(0-offset) self.get_driver().switch_to.window(next_window) return next_window
def append_field(self, element, text): """ Присоединяет переданный текст к элементу. Args: element (Element): элемент text (str): текст Examples: >>> browser.append_field(Find('#field'), 'foo bar baz') """ log_step(f"Append field {element}, '{text}'") field = self._match_first_or_fail(element) field.send_keys(text)
def see_in_field(self, input_element, needle): """ Проверяет, что текст поля ввода равен переданному значению. Args: input_element (Element): Элемент needle (str): Текст Examples: >>> browser.see_in_field(Element("input#foo"), "Hello World!") """ log_step(f"See text '{needle}' in field {input_element}") val = self.grab_value_from(input_element) assert_that(val, equal_to(needle))
def dont_see_element(self, element, attributes={}): """ Проверяет, что элемент невидим. Args: element (Element): Элемент attributes (dict, optional): Атрибуты Raises: AssertionError """ log_step(f"Dont see element {element}, {attributes}") els = self._match_visible(element) els = self._filter_by_attributes(els, attributes) assert_that(els, is_(empty()))
def fill_field(self, element, text): """ Заполняет текстом поле ввода Args: element (Element): Поле ввода text (str): Текст Examples: >>> browser.fill_field(Element("//input[@type='text']"), "Hello World!") """ log_step(f"Fill field {element} with '{text}'") el = self._match_first_or_fail(element) el.clear() el.send_keys(text)
def in_frame(self, frame, exit_to='parent'): log_step(f"In frame {frame}") if exit_to not in ['parent', 'default']: raise TypeError(f"'exit_to' must be 'parent' or 'default', '{exit_to}' given") switch = { 'parent': self.get_driver().switch_to.parent_frame, 'default': self.get_driver().switch_to.default_content } try: self.switch_to_iframe(frame) yield finally: switch[exit_to]()
def grab_visible(self, element): """ Получает видимые элементы. Args: element (Element, optional): Элемент Returns: selenium.webdriver.remote.webelement.WebElement[]: Список элементов Examples: >>> browser.grab_visible(Element("th")) """ log_step(f"Grab visible {element}") return self._match_visible(element)
def open(self, path): """ Переходит по относительному URL (/login, /admin/users, etc ...) Args: path (str): Путь Examples: >>> browser.open("/") # На главную >>> browser.open("/admin") # В админку """ url = urljoin(SettingsManager.get('url'), path) log_step(f"Open {url}") self.get_driver().get(url)
def fill_field_with_delay(self, element, text, delay=0.1): """ Заполняет текстом поле ввода делая паузу между каждым символом. Args: element (Element): Поле ввода text (str): Текст delay (float, optional): Задержка (сек.), по умолчанию 0.1 Examples: >>> browser.fill_field(Element("//input[@type='text']"), "Hello World!", 0.2) """ log_step(f"Fill field {element} with '{text}' & delay '{delay}'") field = self._match_first_or_fail(element) for ch in text: field.send_keys(ch) self.sleep(delay)
def js_click(self, element): """ Click via JS Args: element (Element) """ log_step(f"Click via JS {element}") script = "var rect = arguments[0].getBoundingClientRect();" \ "arguments[0].dispatchEvent(new MouseEvent('click', {" \ " 'bubbles': true," \ " 'cancelable': true," \ " 'view': window," \ " 'clientX': rect.left + rect.width/2," \ " 'clientY': rect.top + rect.height/2" \ "}));" self.execute_js(script, self._match_first_or_fail(element))
def new_window(self, url="about:blank"): """ Открывает новое окно и переключается в него. Args: url (str, optional): По умолчанию 'about:blank' Returns: window handle """ log_step(f"Open new window with url '{url}''") original_handles = self._driver_instance.window_handles self.execute_js(f"window.open('{url}')") new_handles = self._driver_instance.window_handles new_window_hanle = (set(new_handles) - set(original_handles)).pop() self._driver_instance.switch_to.window(new_window_hanle) return new_window_hanle
def wait_for_element_not_visible(self, element, timeout=5, poll_frequency=0.5): """ Ждёт до ``timeout`` сек. исчезновения элемента. Если элемент остался видимым, бросает timeout exception. Args: element (Element): Элемент, который ждём timeout (int, optional): Таймаут ожидания (сек.), по умолчанию 5. Raises: TimeoutException Examples: >>> browser.wait_for_element_not_visible(Element("#header", 15)) """ log_step(f"Wait for element not visible {element}") self.wait(timeout, poll_frequency).until(invisibility_of(element))
def see_text(self, text, element=None): """ Проверяет, что страница содержит текст (с учётом регистра). Можно передать элемент, чтобы искать текст только в нём. Args: text (str): Искомый текст element (Element, optional): Элемент Examples: >>> browser.see_text("Администрирование") >>> browser.see_text("Выйти", Element("h1")) """ log_step(f"See text {text} in {element}") self._enable_implicit_wait() text_from_page = self.grab_visible_text(element) self._disable_implicit_wait() assert_that(text_from_page, contains_string(text))
def element_has_attribute(self, element, attr, expected_value=None): """ Проверяет наличие атрибута у элемента. Опционально приинимает значение атрибута. Args: element (Element): Элемент attr (str): Имя атрибута expected_value (string, optional): Ожидаемое значание Returns: bool Examples: ``<div class='foo bar bazqux'> </div>`` >>> browser.element_has_attribute( Element('div'), 'class' ) True >>> browser.element_has_attribute( Element('div'), 'class', 'foo' ) True >>> browser.element_has_attribute( Element('div'), 'class', 'baz' ) False """ log_step(f"Element {element} has attribute {attr}: {expected_value}") is_attribue_presents = self.execute_js( f"return arguments[0].hasAttribute('{attr}');", self._match_first_or_fail(element) ) if not is_attribue_presents: return False if expected_value is None: return True else: actual_val = self.grab_attribute_from(element, attr) values_list = re.sub(r'\s+', ' ', actual_val).strip().split(' ') if expected_value in values_list: return True else: return False
def load_session_snapshot(self, name): """ Загружает сохранённую сессию. Смотри :func:`~wd.browser.Browser.save_session_snapshot`. Args: name (str): Имя сессии Returns: bool """ log_step(f"Load session snapshot '{name}'") if name not in self._session_snapshots: return False for cookie in self._session_snapshots[name]: self.set_cookie(cookie["name"], cookie["value"], cookie) return True