11 Commits
Author SHA1 Message Date
keitaoouchi ddaf7441cc version++ 2013-01-16 16:39:25 +09:00
keitaoouchi a5f64e9abc Modify Recent Change 2013-01-16 16:39:14 +09:00
keitaoouchi 38ebf2613b Add new properties 2013-01-16 16:37:49 +09:00
keitaoouchi 394f096dab Add supported drivers 2013-01-08 18:58:59 +09:00
keitaoouchi 3707d9f0bf Require selenium>=2.28.0 for PhantomJS support. 2013-01-08 18:39:08 +09:00
keitaoouchi 433b8db2d4 Add PhantomJS Support 2013-01-08 18:37:03 +09:00
keitaoouchi 1339b9c95d Change polling intervals 2013-01-08 18:24:59 +09:00
Keita Oouchi f6a3e91c3f Revised docs 2012-10-08 21:31:06 +09:00
Keita Oouchi 4997a316c1 Fix #4 2012-10-08 21:15:48 +09:00
Keita Oouchi a9ce4718c2 Remove jquery support docs 2012-09-13 23:16:41 +09:00
keitaoouchi ad17ce2f4b Delete jquery support 2012-09-13 18:15:49 +09:00
4 changed files with 121 additions and 102 deletions
+17 -33
View File
@@ -7,6 +7,7 @@ selenium webdriver wrapper to make manipulation easier.
Features
--------
* Support Internet Explorer, Chrome, Opera, Firefox, PhantomJS
* Support remote webdriver.
* Easy to type aliases. (find_element_by_xpath => xpath, etc.)
* Wrapped WebdriverWait( ... ).until( ... ) pattern.
@@ -60,25 +61,10 @@ Each contents in SeleniumContainerWrapper also SeleniumWrapper::
>>> tds = [tr.xpath("//td", eager=True) for tr in br.xpath("//tr", eager=True)]
If current page already load jquery.js, you can find elements by JQuery selector::
>>> buttons = br.jquery('#hoge .fuga li:even')
If current page doesn't load jquery, you can load your local jquery by hand::
>>> br.load_js("/path/to/your/local/jquery.js")
or::
>>> br.load_js(StringIO.StringIO("/path/to/your/local/jquery.js")
You can execute javascript by invoking **script** method::
>>> br.script('alert("hoge")')
Basic API
---------
* seleniumwrapper.create(drivername)
* seleniumwrapper.connect(drivername, executor, custom_capabilities)
Create webdriver instance and wrap it with SeleniumWrapper.
SeleniumWrapper
@@ -94,6 +80,15 @@ SeleniumWrapper
>>> price = br.by_tag("th", "Price").parent.by_tag("td").text
* performance
Returns window.performance wrapped object::
>>> performance = br.performance
>>> timing = performance.timing
>>> navigation = performance.navigation
>>> timing.loadEventEnd
1358319427476
* to_select
Convert wrapped WebElement to raw Select object::
@@ -132,21 +127,6 @@ SeleniumWrapper
>>> br.button("Send").click()
* load_js(path_or_file)
Load javascript from /path/to/file or file like object that responds to 'read' method::
>>> br.load_js("/path/to/jquery.js")
* jquery(target)
Find elements by jquery selector::
>>> br.jquery('#hoge .fuga li:even')
* script(javascript)
Execute given javascript::
>>> br.script('alert("hoge")')
* scroll_to(x, y)
equivalent to javascript's scrollTo::
@@ -263,10 +243,14 @@ SeleniumContainerWrapper
Recent Change
-------------
* 0.4.3
* Add **perfomance**, **performance.timing**, **performance.navigation**, **performance.memory** properties.
* 0.4.2
* Add 'PhantomJS' support.
* 0.4.1
* Fixed some bugs.
* 0.4.0
* Added **scroll_to**, **scroll_by**, **scroll_into_view** methods.
* Added **jquery** method to support jquery selecter.
* Added **load_js**, **script** methods.
* 0.3.5
* Added **attr** method.
* Fixed some typos.
+2 -2
View File
@@ -22,14 +22,14 @@ classifiers = [
'Topic :: Software Development :: Libraries :: Python Modules'
]
requires = ['selenium>=2.25.0']
requires = ['selenium>=2.28.0']
setup(
author='Keita Oouchi',
author_email='keita.oouchi@gmail.com',
url = 'https://github.com/keitaoouchi/seleniumwrapper',
name = 'seleniumwrapper',
version = '0.4.0',
version = '0.4.3',
package_dir={"":"src"},
packages = ['seleniumwrapper'],
test_suite = "test_seleniumwrapper.suite",
+95 -42
View File
@@ -6,7 +6,7 @@ import inspect
import time
import random
import selenium
from selenium.webdriver import Ie, Opera, Chrome, Firefox
from selenium.webdriver import Ie, Opera, Chrome, Firefox, PhantomJS
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import WebDriverWait
@@ -23,7 +23,8 @@ def create(drivername, *args, **kwargs):
drivers = {'ie': Ie,
'opera': Opera,
'chrome': Chrome,
'firefox': Firefox}
'firefox': Firefox,
'phantomjs': PhantomJS}
dname = drivername.lower()
if dname in drivers:
try:
@@ -31,7 +32,8 @@ def create(drivername, *args, **kwargs):
except Exception as e:
raise e
else:
msg = "drivername should be one of [IE, Opera, Chrome, Firefox](case-insentive). given {0}".format(drivername)
msg = "".join(("drivername should be one of [IE, Opera, Chrome, Firefox, PhantomJS]",
"(case-insentive). given {0}".format(drivername)))
raise ValueError(msg)
@@ -49,7 +51,8 @@ def connect(drivername, executor, custom_capabilities=None, **kwargs):
'opera': DesiredCapabilities.OPERA,
'chrome': DesiredCapabilities.CHROME,
'firefox': DesiredCapabilities.FIREFOX,
'android': DesiredCapabilities.ANDROID}
'android': DesiredCapabilities.ANDROID,
'phatomjs': DesiredCapabilities.PHANTOMJS}
dname = drivername.lower()
if dname in capabilities:
capability = capabilities[dname]
@@ -62,7 +65,8 @@ def connect(drivername, executor, custom_capabilities=None, **kwargs):
except Exception as e:
raise e
else:
msg = "drivername should be one of [IE, Opera, Chrome, Firefox](case-insentive). given {0}".format(drivername)
msg = "".join(("drivername should be one of [IE, Opera, Chrome, Firefox, PhantomJS]",
"(case-insentive). given {0}".format(drivername)))
raise ValueError(msg)
@@ -86,7 +90,6 @@ def _chainreact(__getattr__):
def reaction(*realargs):
result = methodobj(*realargs)
# for side-effective method(append, ...)
result = result if result is not None else self
return wrap_or_else(result)
return reaction
@@ -95,6 +98,71 @@ def _chainreact(__getattr__):
return containment
class Performance(object):
def __init__(self, performance):
if not isinstance(performance, dict):
raise AttributeError('Wrapped performance object should be an instance of dict.')
self._performance = performance
@property
def memory(self):
if 'memory' in self._performance:
return Memory(self._performance['memory'])
raise AttributeError('window.performance.memory is not supported in this browser.')
@property
def navigation(self):
if 'navigation' in self._performance:
return Navigation(self._performance['navigation'])
raise AttributeError('window.performance.navigation is not supported in this browser.')
@property
def timing(self):
if 'timing' in self._performance:
return Timing(self._performance['timing'])
raise AttributeError('window.performance.timing is not supported in this browser.')
class Memory(object):
def __init__(self, memory):
self._memory = memory
def __getattr__(self, name):
return self._memory[name]
@property
def __dict__(self):
return self._memory
def __iter__(self):
return iter(self._memory)
class Navigation(object):
def __init__(self, navigation):
self._navigation = navigation
def __getattr__(self, name):
return self._navigation[name]
@property
def __dict__(self):
return self._navigation
def __iter__(self):
return iter(self._navigation)
class Timing(object):
def __init__(self, timing):
self._timing = timing
def __getattr__(self, name):
return self._timing[name]
@property
def __dict__(self):
return self._timing
def __iter__(self):
return iter(self._timing)
class SeleniumWrapper(object):
def __init__(self, driver):
@@ -109,6 +177,24 @@ class SeleniumWrapper(object):
def unwrap(self):
return self._wrapped
@property
def performance(self):
if isinstance(self._wrapped, WebDriver):
if self._wrapped.execute_script("return 'performance' in window;"):
timeout = time.time() + 120
script = "return window.performance.timing.loadEventEnd;"
executor = self._wrapped.execute_script
while time.time() < timeout and not executor(script):
time.sleep(0.2)
if not executor(script):
raise Exception('Timeout!')
performance = self._wrapped.execute_script('return window.performance;')
return Performance(performance)
else:
raise AttributeError("This browser is not supporting Timing APIs.")
else:
raise AttributeError("'WebElement' object has not attribute 'performance'")
@property
def parent(self):
if isinstance(self._wrapped, WebElement):
@@ -226,47 +312,14 @@ class SeleniumWrapper(object):
try:
if presleep:
time.sleep(presleep)
self._wait_until_stopping(timeout, 0.1)
self._wait_until_displayed(timeout, 0.3)
self._wait_until_clickable(timeout, 0.3)
self._wait_until_stopping(timeout, 0.01)
self._wait_until_displayed(timeout, 0.01)
self._wait_until_clickable(timeout, 0.01)
if postsleep:
time.sleep(postsleep)
except Exception as e:
raise e
def load_js(self, path_or_file):
"""Load javascript from /path/to/file or file like object that responds to 'read' method."""
if isinstance(path_or_file, str) and os.path.isfile(path_or_file):
with open(path_or_file, 'r') as f:
library = f.read()
self._wrapped.execute_script(library)
elif hasattr(path_or_file, 'read'):
library = path_or_file.read()
self._wrapped.execute_script(library)
else:
raise AttributeError('Given argument is not both file or /path/to/file:: {0}'.format(str(path_or_file)))
def jquery(self, target):
"""Returns SeleniumContainerWrapper if any elements is found."""
script = "try{{return $('{0}');}}catch(e){{}}".format(target)
result = self._wrapped.execute_script(script)
if result:
if isinstance(result, collections.Sequence):
return SeleniumContainerWrapper(result)
else:
return SeleniumWrapper(result)
else:
raise NoSuchElementException("Target {0} not found.".format(target))
def script(self, javascript, *args):
"""Synchronously execute given javascript."""
result = self._wrapped.execute_script(javascript, *args)
if result:
if isinstance(result, collections.Sequence):
return SeleniumContainerWrapper(result)
else:
return SeleniumWrapper(result)
def scroll_to(self, x, y):
if isinstance(self._wrapped, WebDriver):
return self._wrapped.execute_script("window.scrollTo({:d}, {:d})".format(x, y))
+7 -25
View File
@@ -135,6 +135,13 @@ class TestSeleniumWrapper(unittest.TestCase):
wrapper = SeleniumWrapper(mocked_element)
self.assertIsInstance(wrapper.unwrap, WebElement)
def test_execute_script_should_return_None_if_null_was_returned(self):
mocked_driver = mock.Mock(WebDriver)
mocked_driver.execute_script.return_value = None
driver = SeleniumWrapper(mocked_driver)
obj = driver.execute_script('return null')
self.assertIsNone(obj)
class TestSeleniumWrapperAliases(unittest.TestCase):
def setUp(self):
@@ -209,31 +216,6 @@ class TestSeleniumWrapperJavascriptSupport(unittest.TestCase):
mocky = mock.Mock(WebDriver)
self.mock = mocky
def test_load_js_raise_if_given_argument_is_not_both_file_like_obj_or_path_to_file(self):
wrapper = SeleniumWrapper(self.mock)
self.assertRaises(AttributeError, wrapper.load_js, "/path/not/exists")
self.assertRaises(AttributeError, wrapper.load_js, 1)
def test_load_js_load_string_from_StringIO_because_it_respond_to_read_method(self):
f = StringIO.StringIO('hoge')
wrapper = SeleniumWrapper(self.mock)
wrapper.load_js(f)
self.mock.execute_script.assert_called_once_with('hoge')
def test_script_returns_if_something_is_returned_by_execute_script(self):
self.mock.execute_script.return_value = [mock.Mock(WebElement)]
wrapper = SeleniumWrapper(self.mock)
self.assertIsInstance(wrapper.script('fuga'), SeleniumContainerWrapper)
self.mock.execute_script.return_value = mock.Mock(WebElement)
self.assertIsInstance(wrapper.script('fuga'), SeleniumWrapper)
self.mock.execute_script.return_value = None
self.assertIsNone(wrapper.script('fuga'))
def test_jquery_raise_if_nothing_found(self):
self.mock.execute_script.return_value = None
wrapper = SeleniumWrapper(self.mock)
self.assertRaises(NoSuchElementException, wrapper.jquery, 'hoge')
def test_scroll_methods_raise_if_wrapped_is_not_webdriver(self):
wrapper = SeleniumWrapper(mock.Mock(WebElement))
self.assertRaises(AttributeError, wrapper.scroll_to, *[10, 10])