zoukankan      html  css  js  c++  java
  • splinter webdriver API 的基本实现

    # -*- coding: utf-8 -*-
    
    # Copyright 2012 splinter authors. All rights reserved.
    # Use of this source code is governed by a BSD-style
    # license that can be found in the LICENSE file.
    
    from __future__ import with_statement
    import logging
    import subprocess
    import time
    import re
    from contextlib import contextmanager
    
    from selenium.common.exceptions import NoSuchElementException
    from selenium.webdriver.common.action_chains import ActionChains
    
    from splinter.driver import DriverAPI, ElementAPI
    from splinter.element_list import ElementList
    from splinter.utils import warn_deprecated
    from tempfile import TemporaryFile
    
    
    class BaseWebDriver(DriverAPI):
        old_popen = subprocess.Popen
    
        def __init__(self, wait_time=2):
            self.wait_time = wait_time
    
        def _patch_subprocess(self):
            loggers_to_silence = [
                'selenium.webdriver.firefox.extension_connection',
                'selenium.webdriver.remote.remote_connection',
                'selenium.webdriver.remote.utils',
            ]
    
            class MutedHandler(logging.Handler):
                pass
    
            for name in loggers_to_silence:
                logger = logging.getLogger(name)
                logger.addHandler(MutedHandler())
                logger.setLevel(99999)
    
            # selenium is such a verbose guy let's make it open the
            # browser without showing all the meaningless output
            def MyPopen(*args, **kw):
                kw['stdout'] = TemporaryFile()
                kw['stderr'] = TemporaryFile()
                kw['close_fds'] = True
                return self.old_popen(*args, **kw)
    
            subprocess.Popen = MyPopen
    
        def _unpatch_subprocess(self):
            # cleaning up the house
            subprocess.Popen = self.old_popen
    
        def __enter__(self):
            return self
    
        def __exit__(self, exc_type, exc_value, traceback):
            self.quit()
    
        @property
        def title(self):
            return self.driver.title
    
        @property
        def html(self):
            return self.driver.page_source
    
        @property
        def url(self):
            return self.driver.current_url
    
        def visit(self, url):
            self.connect(url)
            self.ensure_success_response()
            self.driver.get(url)
    
        def back(self):
            self.driver.back()
    
        def forward(self):
            self.driver.forward()
    
        def reload(self):
            self.driver.refresh()
    
        def execute_script(self, script):
            self.driver.execute_script(script)
    
        def evaluate_script(self, script):
            return self.driver.execute_script("return %s" % script)
    
        def is_element_present(self, finder, selector, wait_time=None):
            wait_time = wait_time or self.wait_time
            end_time = time.time() + wait_time
    
            while time.time() < end_time:
                if finder(selector):
                    return True
            return False
    
        def is_element_not_present(self, finder, selector, wait_time=None):
            wait_time = wait_time or self.wait_time
            end_time = time.time() + wait_time
    
            while time.time() < end_time:
                if not finder(selector):
                    return True
            return False
    
        def is_element_present_by_css(self, css_selector, wait_time=None):
            return self.is_element_present(self.find_by_css, css_selector, wait_time)
    
        def is_element_not_present_by_css(self, css_selector, wait_time=None):
            return self.is_element_not_present(self.find_by_css, css_selector, wait_time)
    
        def is_element_present_by_xpath(self, xpath, wait_time=None):
            return self.is_element_present(self.find_by_xpath, xpath, wait_time)
    
        def is_element_not_present_by_xpath(self, xpath, wait_time=None):
            return self.is_element_not_present(self.find_by_xpath, xpath, wait_time)
    
        def is_element_present_by_tag(self, tag, wait_time=None):
            return self.is_element_present(self.find_by_tag, tag, wait_time)
    
        def is_element_not_present_by_tag(self, tag, wait_time=None):
            return self.is_element_not_present(self.find_by_tag, tag, wait_time)
    
        def is_element_present_by_name(self, name, wait_time=None):
            return self.is_element_present(self.find_by_name, name, wait_time)
    
        def is_element_not_present_by_name(self, name, wait_time=None):
            return self.is_element_not_present(self.find_by_name, name, wait_time)
    
        def is_element_present_by_value(self, value, wait_time=None):
            return self.is_element_present(self.find_by_value, value, wait_time)
    
        def is_element_not_present_by_value(self, value, wait_time=None):
            return self.is_element_not_present(self.find_by_value, value, wait_time)
    
        def is_element_present_by_id(self, id, wait_time=None):
            return self.is_element_present(self.find_by_id, id, wait_time)
    
        def is_element_not_present_by_id(self, id, wait_time=None):
            return self.is_element_not_present(self.find_by_id, id, wait_time)
    
        def get_alert(self):
            return AlertElement(self.driver.switch_to_alert())
    
        def is_text_present(self, text, wait_time=None):
            wait_time = wait_time or self.wait_time
            end_time = time.time() + wait_time
    
            while time.time() < end_time:
                try:
                    self.driver.find_element_by_tag_name('body').text.index(text)
                    return True
                except ValueError:
                    pass
            return False
    
        def is_text_not_present(self, text, wait_time=None):
            wait_time = wait_time or self.wait_time
            end_time = time.time() + wait_time
    
            while time.time() < end_time:
                try:
                    self.driver.find_element_by_tag_name('body').text.index(text)
                except ValueError:
                    return True
            return False
    
        @contextmanager
        def get_iframe(self, id):
            self.driver.switch_to_frame(id)
            try:
                yield self
            finally:
                self.driver.switch_to_frame(None)
    
        def find_option_by_value(self, value):
            return self.find_by_xpath('//option[@value="%s"]' % value, original_find="option by value", original_query=value)
    
        def find_option_by_text(self, text):
            return self.find_by_xpath('//option[normalize-space(text())="%s"]' % text, original_find="option by text", original_query=text)
    
        def find_link_by_href(self, href):
            return self.find_by_xpath('//a[@href="%s"]' % href, original_find="link by href", original_query=href)
    
        def find_link_by_partial_href(self, partial_href):
            return self.find_by_xpath('//a[contains(@href, "%s")]' % partial_href, original_find="link by partial href", original_query=partial_href)
    
        def find_link_by_partial_text(self, partial_text):
            return self.find_by_xpath('//a[contains(text(), "%s")]' % partial_text, original_find="link by partial text", original_query=partial_text)
    
        def find_link_by_text(self, text):
            return self.find_by_xpath('//a[text()="%s"]' % text, original_find="link by text", original_query=text)
    
        def find_by(self, finder, selector, original_find=None, original_query=None):
            elements = None
            end_time = time.time() + self.wait_time
    
            func_name = finder.im_func.func_name
            find_by = original_find or func_name[func_name.rfind('_by_') + 4:]
            query = original_query or selector
    
            while time.time() < end_time:
                try:
                    elements = finder(selector)
                    if not isinstance(elements, list):
                        elements = [elements]
                except NoSuchElementException:
                    pass
    
                if elements:
                    return ElementList([self.element_class(element, self) for element in elements], find_by=find_by, query=query)
            return ElementList([], find_by=find_by, query=query)
    
        def find_by_css(self, css_selector):
            return self.find_by(self.driver.find_elements_by_css_selector, css_selector, original_find='css', original_query=css_selector)
    
        def find_by_xpath(self, xpath, original_find=None, original_query=None):
            original_find = original_find or "xpath"
            original_query = original_query or xpath
            return self.find_by(self.driver.find_elements_by_xpath, xpath, original_find=original_find, original_query=original_query)
    
        def find_by_name(self, name):
            return self.find_by(self.driver.find_elements_by_name, name)
    
        def find_by_tag(self, tag):
            return self.find_by(self.driver.find_elements_by_tag_name, tag)
    
        def find_by_value(self, value):
            return self.find_by_xpath('//*[@value="%s"]' % value, original_find='value', original_query=value)
    
        def find_by_id(self, id):
            return self.find_by(self.driver.find_element_by_id, id)
    
        def fill(self, name, value):
            field = self.find_by_name(name).first
            field.value = value
    
        attach_file = fill
    
        def fill_form(self, field_values):
            for name, value in field_values.items():
                elements = self.find_by_name(name)
                element = elements.first
                if element['type'] == 'text' or element.tag_name == 'textarea':
                    element.value = value
                elif element['type'] == 'checkbox':
                    if value:
                        element.check()
                    else:
                        element.uncheck()
                elif element['type'] == 'radio':
                    for field in elements:
                        if field.value == value:
                            field.click()
                elif element._element.tag_name == 'select':
                    element.find_by_value(value).first._element.click()
    
        def type(self, name, value, slowly=False):
            element = self.driver.find_element_by_css_selector('input[name="%s"]' % name)
            if slowly:
                return TypeIterator(element, value)
            element.send_keys(value)
            return value
    
        def choose(self, name, value):
            fields = self.find_by_name(name)
            for field in fields:
                if field.value == value:
                    field.click()
    
        def check(self, name):
            self.find_by_name(name).first.check()
    
        def uncheck(self, name):
            self.find_by_name(name).first.uncheck()
    
        def select(self, name, value):
            self.find_by_xpath('//select[@name="%s"]/option[@value="%s"]' % (name, value)).first._element.click()
    
        def quit(self):
            self.driver.quit()
    
        @property
        def cookies(self):
            return self._cookie_manager
    
    
    class TypeIterator(object):
    
    
        def __init__(self, element, keys):
            self._element = element
            self._keys = keys
    
        def __iter__(self):
            for key in self._keys:
                self._element.send_keys(key)
                yield key
    
    
    class WebDriverElement(ElementAPI):
    
        def __init__(self, element, parent):
            self._element = element
            self.parent = parent
            self.action_chains = ActionChains(parent.driver)
    
        def _get_value(self):
            return self["value"] or self._element.text
    
        def _set_value(self, value):
            if self._element.get_attribute('type') != 'file':
                self._element.clear()
            self._element.send_keys(value)
    
        value = property(_get_value, _set_value)
    
        @property
        def text(self):
            return self._element.text
    
        @property
        def tag_name(self):
            return self._element.tag_name
    
        def fill(self, value):
            self.value = value
    
        def type(self, value, slowly=False):
            if slowly:
                return TypeIterator(self._element, value)
    
            self._element.send_keys(value)
            return value
    
        def click(self):
            self._element.click()
    
        def check(self):
            if not self.checked:
                self._element.click()
    
        def uncheck(self):
            if self.checked:
                self._element.click()
    
        @property
        def checked(self):
            return self._element.is_selected()
    
        selected = checked
    
        @property
        def visible(self):
            return self._element.is_displayed()
    
        def find_by_css(self, selector, original_find=None, original_query=None):
            find_by = original_find or 'css'
            query = original_query or selector
    
            elements = self._element.find_elements_by_css_selector(selector)
            return ElementList([self.__class__(element, self.parent) for element in elements], find_by=find_by, query=query)
    
        def find_by_xpath(self, selector):
            elements = ElementList(self._element.find_elements_by_xpath(selector))
            return ElementList([self.__class__(element, self.parent) for element in elements], find_by='xpath', query=selector)
    
        def find_by_name(self, name):
            elements = ElementList(self._element.find_elements_by_name(name))
            return ElementList([self.__class__(element, self.parent) for element in elements], find_by='name', query=name)
    
        def find_by_tag(self, tag):
            elements = ElementList(self._element.find_elements_by_tag_name(tag))
            return ElementList([self.__class__(element, self.parent) for element in elements], find_by='tag', query=tag)
    
        def find_by_value(self, value):
            selector = '[value="%s"]' % value
            return self.find_by_css(selector, original_find='value', original_query=value)
    
        def find_by_id(self, id):
            elements = ElementList(self._element.find_elements_by_id(id))
            return ElementList([self.__class__(element, self.parent) for element in elements], find_by='id', query=id)
    
        def has_class(self, class_name):
            element_class_name = self._element.get_attribute('class')
            return bool(re.search(r'(?:^|\s)' + re.escape(class_name) + r'(?:$|\s)', element_class_name))
    
        def mouse_over(self):
            """
            Performs a mouse over the element.
    
            Currently works only on Chrome driver.
            """
            self.action_chains.move_to_element(self._element)
            self.action_chains.perform()
    
        def mouse_out(self):
            """
            Performs a mouse out the element.
    
            Currently works only on Chrome driver.
            """
            self.action_chains.move_by_offset(5000, 5000)
            self.action_chains.perform()
    
        mouseover = warn_deprecated(mouse_over, 'mouseover')
        mouseout = warn_deprecated(mouse_out, 'mouseout')
    
        def double_click(self):
            """
            Performs a double click in the element.
    
            Currently works only on Chrome driver.
            """
            self.action_chains.double_click(self._element)
            self.action_chains.perform()
    
        def right_click(self):
            """
            Performs a right click in the element.
    
            Currently works only on Chrome driver.
            """
            self.action_chains.context_click(self._element)
            self.action_chains.perform()
    
        def drag_and_drop(self, droppable):
            """
            Performs drag a element to another elmenet.
    
            Currently works only on Chrome driver.
            """
            self.action_chains.drag_and_drop(self._element, droppable._element)
            self.action_chains.perform()
    
        def __getitem__(self, attr):
            return self._element.get_attribute(attr)
    
    
    class AlertElement(object):
    
        def __init__(self, alert):
            self._alert = alert
            self.text = alert.text
    
        def accept(self):
            self._alert.accept()
    
        def dismiss(self):
            self._alert.dismiss()
    
        def fill_with(self, text):
            self._alert.send_keys(text)
    
        def __enter__(self):
            return self
    
        def __exit__(self, type, value, traceback):
            pass
  • 相关阅读:
    permission 文档 翻译 运行时权限
    TabLayout ViewPager Fragment 简介 案例 MD
    Log 日志工具类 保存到文件 MD
    OkHttp 官方wiki 翻译 MD
    Okhttp 简介 示例 MD
    OkHttp 官方Wiki之【使用案例】
    DialogPlus
    倒计时 总结 Timer Handler CountDownTimer RxJava MD
    RecyclerView 判断滑到底部 顶部 预加载 更多 分页 MD
    CSS3的媒体查询(Media Queries)与移动设备显示尺寸大全
  • 原文地址:https://www.cnblogs.com/hzhida/p/2634553.html
Copyright © 2011-2022 走看看