diff --git a/.gitmodules b/.gitmodules index 39a77781529bf8..12cee69142f1ed 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,3 +15,6 @@ [submodule "pytest"] path = pytest url = https://github.com/pytest-dev/pytest.git +[submodule "webdriver"] + path = webdriver + url = https://github.com/w3c/wdclient.git diff --git a/localpaths.py b/localpaths.py index c88e4f4cee2f84..2d8d7e20359908 100644 --- a/localpaths.py +++ b/localpaths.py @@ -10,3 +10,4 @@ sys.path.insert(0, os.path.join(repo_root, "tools", "wptserve")) sys.path.insert(0, os.path.join(repo_root, "tools", "pywebsocket", "src")) sys.path.insert(0, os.path.join(repo_root, "tools", "pytest")) +sys.path.insert(0, os.path.join(repo_root, "tools", "webdriver")) diff --git a/webdriver b/webdriver new file mode 160000 index 00000000000000..56886b0d7ed043 --- /dev/null +++ b/webdriver @@ -0,0 +1 @@ +Subproject commit 56886b0d7ed04354068d3bda2fdac7156da2305b diff --git a/webdriver/webdriver/__init__.py b/webdriver/webdriver/__init__.py deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/webdriver/webdriver/alert.py b/webdriver/webdriver/alert.py deleted file mode 100644 index 0dee3127d297ef..00000000000000 --- a/webdriver/webdriver/alert.py +++ /dev/null @@ -1,26 +0,0 @@ -"""WebDriver alert handling.""" - -class Alert(object): - """Class that provides access to the WebDriver alert handling functions.""" - - def __init__(self, driver): - self._driver = driver - - def _execute(self, method, path, name, body=None): - return self._driver.execute(method, path, name, body) - - def dismiss(self): - """Dismiss the alert.""" - self._execute('POST', '/dismiss_alert', 'dismiss') - - def accept(self): - """Accept the alert.""" - self._execute('POST', '/accept_alert', 'accept') - - def get_text(self): - """Get the text displayed in the alert.""" - return self._execute('GET', '/alert_text', 'getText') - - def send_keys(self, keys): - """Type into the text input of the alert if available.""" - self._execute('POST', '/alert_text', 'sendKeys', { 'text': keys }) diff --git a/webdriver/webdriver/capabilities.py b/webdriver/webdriver/capabilities.py deleted file mode 100644 index 44bb1fd647d45d..00000000000000 --- a/webdriver/webdriver/capabilities.py +++ /dev/null @@ -1,30 +0,0 @@ -"""Definition of various capability-related constants.""" - -class Capability: - """Standard capability names.""" - BROWSER_NAME = 'browserName' - BROWSER_VERSION = 'browserVersion' - PAGE_LOADING_STRATEGY = 'pageLoadingStrategy' - PLATFORM_NAME = 'platformName' - PLATFORM_VERSION = 'platformVersion' - SECURE_SSL = 'secureSsl' - TAKES_SCREENSHOT = 'takesScreenshot' - TAKE_ELEMENT_SCREENSHOT = 'takeElementScreenshot' - TOUCH_ENABLED = 'touchEnabled' - -class Platform: - """Standard OS names.""" - ANY = 'any' - ANDROID = 'android' - IOS = 'ios' - LINUX = 'linux' - MAC = 'mac' - UNIX = 'unix' - WINDOW = 'windows' - -class PageLoadingStrategy: - """Standard page loading strategies.""" - CONSERVATIVE = 'conservative' - NORMAL = 'normal' - EAGER = 'eager' - NONE = 'none' diff --git a/webdriver/webdriver/command.py b/webdriver/webdriver/command.py deleted file mode 100644 index 4ea162fea125a0..00000000000000 --- a/webdriver/webdriver/command.py +++ /dev/null @@ -1,111 +0,0 @@ -"""Dispatches requests to remote WebDriver endpoint.""" - -import exceptions - -import httplib -import json -import urlparse -import webelement - -class CommandExecutor(object): - """Dispatches requests to remote WebDriver endpoint.""" - - _HEADERS = { - "User-Agent": "Python WebDriver Local End", - "Content-Type": "application/json;charset=\"UTF-8\"", - "Accept": "application/json", - "Accept-Charset": "utf-8", - "Accept-Encoding": "identity", - "Connection": "close", - } - - def __init__(self, url, mode='strict'): - self._parsed_url = urlparse.urlparse(url) - self._conn = httplib.HTTPConnection(self._parsed_url.hostname, - self._parsed_url.port) - self._mode = mode - - def execute(self, - method, - path, - session_id, - name, - parameters=None, - object_hook=None): - """Execute a command against the WebDriver endpoint. - - Arguments: - method -- one of GET, POST, DELETE - path -- the path of the url endpoint (needs to include - session/ if needed) - session_id -- the sessionId to include in the JSON body - name -- name of the command that is being executed to include in - the JSON body - parameters -- the JSON body to send with the command. Only used if - method is POST - object_hook -- function used by json.loads to properly deserialize - objects in the request - """ - if self._mode == 'strict': - return self._execute_strict( - method, path, session_id, name, parameters, object_hook) - elif self._mode == 'compatibility': - return self._execute_compatibility( - method, path, session_id, name, parameters, object_hook) - else: - raise Exception("Unknown mode: " + self._mode) - - def _execute_compatibility(self, - method, - path, - session_id, - name, - parameters, - object_hook): - body = {'sessionId': session_id, 'name': name } - if parameters: - body.update(parameters) - - self._conn.request( - method, - self._parsed_url.path + path, - json.dumps(body, default = self._json_encode).encode('utf-8'), - self._HEADERS) - resp = self._conn.getresponse() - data = resp.read().decode('utf-8') - if data: - data = json.loads(data, object_hook = object_hook) - if data['status'] != 0: - raise exceptions.create_webdriver_exception_compatibility( - data['status'], data['value']['message']) - return data - if resp.status < 200 or resp.status > 299: - raise exceptions.create_webdriver_exception_compatibility( - resp.status, resp.reason) - - def _execute_strict(self, - method, - path, - session_id, - name, - parameters, - object_hook): - body = { - 'sessionId': session_id, - 'name': name, - 'parameters': parameters } - self._conn.request( - method, - self._parsed_url.path + path, - json.dumps(body, default = self._json_encode).encode('utf-8'), - self._HEADERS) - resp = self._conn.getresponse() - data = json.loads( - resp.read().decode('utf-8'), object_hook = object_hook) - if data['status'] != 'success': - raise exceptions.create_webdriver_exception_strict( - data['status'], data['value']) - return data - - def _json_encode(self, obj): - return obj.to_json() diff --git a/webdriver/webdriver/driver.py b/webdriver/webdriver/driver.py deleted file mode 100644 index 27d543ed22b92b..00000000000000 --- a/webdriver/webdriver/driver.py +++ /dev/null @@ -1,199 +0,0 @@ -"""Entry point for WebDriver.""" - -import alert -import command -import searchcontext -import webelement - -import base64 - - -class WebDriver(searchcontext.SearchContext): - """Controls a web browser.""" - - def __init__(self, host, required, desired, mode='strict'): - args = { 'desiredCapabilities': desired } - if required: - args['requiredCapabilities'] = required - - self._executor = command.CommandExecutor(host, mode) - - resp = self._executor.execute( - 'POST', '/session', None, 'newSession', args) - self.capabilities = resp['value'] - self._session_id = resp['sessionId'] - self.mode = mode - - def execute(self, method, path, name, parameters= None): - """Execute a command against the current WebDriver session.""" - data = self._executor.execute( - method, - '/session/' + self._session_id + path, - self._session_id, - name, - parameters, - self._object_hook) - if data: - return data['value'] - - def get(self, url): - """Navigate to url.""" - self.execute('POST', '/url', 'get', { 'url': url }) - - def get_current_url(self): - """Get the current value of the location bar.""" - return self.execute('GET', '/url', 'getCurrentUrl') - - def go_back(self): - """Hit the browser back button.""" - self.execute('POST', '/back', 'goBack') - - def go_forward(self): - """Hit the browser forward button.""" - self.execute('POST', '/forward', 'goForward') - - def refresh(self): - """Refresh the current page in the browser.""" - self.execute('POST', '/refresh', 'refresh') - - def quit(self): - """Shutdown the current WebDriver session.""" - self.execute('DELETE', '', 'quit') - - def get_window_handle(self): - """Get the handle for the browser window/tab currently accepting - commands. - """ - return self.execute('GET', '/window_handle', 'getWindowHandle') - - def get_window_handles(self): - """Get handles for all open windows/tabs.""" - return self.execute('GET', '/window_handles', 'getWindowHandles') - - def close(self): - """Close the current tab or window. - - If this is the last tab or window, then this is the same as - calling quit. - """ - self.execute('DELETE', '/window', 'close') - - def maximize_window(self): - """Maximize the current window.""" - return self._window_command('POST', '/maximize', 'maximize') - - def get_window_size(self): - """Get the dimensions of the current window.""" - result = self._window_command('GET', '/size', 'getWindowSize') - return {'height': result['height'], 'width': result['width']} - - def set_window_size(self, height, width): - """Set the size of the current window.""" - self._window_command( - 'POST', - '/size', - 'setWindowSize', - { 'height': height, 'width': width}) - - def fullscreen_window(self): - """Make the current window fullscreen.""" - pass # implement when end point is defined - - def switch_to_window(self, name): - """Switch to the window with the given handle or name.""" - self.execute('POST', '/window', 'switchToWindow', { 'name': name }) - - def switch_to_frame(self, id): - """Switch to a frame. - - id can be either a WebElement or an integer. - """ - self.execute('POST', '/frame', 'switchToFrame', { 'id': id}) - - def switch_to_parent_frame(self): - """Move to the browsing context containing the currently selected frame. - - If in the top-level browsing context, this is a no-op. - """ - self.execute('POST', '/frame/parent', 'switchToParentFrame') - - def switch_to_alert(self): - """Return an Alert object to interact with a modal dialog.""" - alert_ = alert.Alert(self) - alert_.get_text() - return alert_ - - def execute_script(self, script, args=[]): - """Execute a Javascript script in the current browsing context.""" - return self.execute( - 'POST', - '/execute', - 'executeScript', - { 'script': script, 'args': args }) - - def execute_script_async(self, script, args=[]): - """Execute a Javascript script in the current browsing context.""" - return self.execute( - 'POST', - '/execute_async', - 'executeScriptAsync', - { 'script': script, 'args': args }) - - def take_screenshot(self, element=None): - """Take a screenshot. - - If element is not provided, the screenshot should be of the - current page, otherwise the screenshot should be of the given element. - """ - if self.mode == 'strict': - pass # implement when endpoint is defined - elif self.mode == 'compatibility': - if element: - pass # element screenshots are unsupported in compatibility - else: - return base64.standard_b64decode( - self.execute('GET', '/screenshot', 'takeScreenshot')) - - def add_cookie(self, cookie): - """Add a cookie to the browser.""" - self.execute('POST', '/cookie', 'addCookie', { 'cookie': cookie }) - - def get_cookie(self, name = None): - """Get the cookies accessible from the current page.""" - if self.mode == 'compatibility': - cookies = self.execute('GET', '/cookie', 'getCookie') - if name: - cookies_ = [] - for cookie in cookies: - if cookie['name'] == name: - cookies_.append(cookie) - return cookies_ - return cookies - elif self.mode == 'strict': - pass # implement when wire protocol for this has been defined - - def set_implicit_timeout(self, ms): - self._set_timeout('implicit', ms) - - def set_page_load_timeout(self, ms): - self._set_timeout('page load', ms) - - def set_script_timeout(self, ms): - self._set_timeout('script', ms) - - def _set_timeout(self, type, ms): - params = { 'type': type, 'ms': ms } - self.execute('POST', '/timeouts', 'timeouts', params) - - def _window_command(self, method, path, name, parameters = None): - if self.mode == 'compatibility': - return self.execute( - method, '/window/current' + path, name, parameters) - elif self.mode == 'strict': - pass # implement this when end-points are defined in doc - - def _object_hook(self, obj): - if 'ELEMENT' in obj: - return webelement.WebElement(self, obj['ELEMENT']) - return obj - diff --git a/webdriver/webdriver/exceptions.py b/webdriver/webdriver/exceptions.py deleted file mode 100644 index 33f63ea581176f..00000000000000 --- a/webdriver/webdriver/exceptions.py +++ /dev/null @@ -1,166 +0,0 @@ -"""Definition of WebDriverException classes.""" - -def create_webdriver_exception_strict(status_code, message): - """Create the appropriate WebDriverException given the status_code.""" - if status_code in _exceptions_strict: - return _exceptions_strict[status_code](message) - return UnknownStatusCodeException("[%s] %s" % (status_code, message)) - -def create_webdriver_exception_compatibility(status_code, message): - """Create the appropriate WebDriverException given the status_code.""" - if status_code in _exceptions_compatibility: - return _exceptions_compatibility[status_code](message) - return UnknownStatusCodeException("[%s] %s" % (status_code, message)) - -class WebDriverException(Exception): - """Base class for all WebDriverExceptions.""" - -class UnableToSetCookieException(WebDriverException): - """A request to set a cookie's value could not be satisfied.""" - -class InvalidElementStateException(WebDriverException): - """An element command could not be completed because the element is - in an invalid state (e.g. attempting to click an element that is no - longer attached to the DOM). - """ - -class NoSuchElementException(WebDriverException): - """An element could not be located on the page using the given - search parameters. - """ - -class TimeoutException(WebDriverException): - """An operation did not complete before its timeout expired.""" - -class ElementNotSelectableException(InvalidElementStateException): - """An attempt was made to select an element that cannot be selected.""" - -class ElementNotVisibleException(InvalidElementStateException): - """An element command could not be completed because the element is - not visible on the page. - """ - -class ImeEngineActivationFailedException(WebDriverException): - """An IME engine could not be started.""" - -class ImeNotAvailableException(ImeEngineActivationFailedException): - """IME was not available.""" - -class InvalidCookieDomainException(UnableToSetCookieException): - """An illegal attempt was made to set a cookie under a different - domain than the current page. - """ - -class InvalidElementCoordinatesException(WebDriverException): - """The coordinates provided to an interactions operation are invalid.""" - -class InvalidSelectorException(NoSuchElementException): - """Argument was an invalid selector (e.g. XPath/CSS).""" - -class JavascriptErrorException(WebDriverException): - """An error occurred while executing user supplied JavaScript.""" - -class MoveTargetOutOfBoundsException(InvalidElementStateException): - """The target for mouse interaction is not in the browser's viewport - and cannot be brought into that viewport. - """ - -class NoSuchAlertException(WebDriverException): - """An attempt was made to operate on a modal dialog when one was not open.""" - -class NoSuchFrameException(WebDriverException): - """A request to switch to a frame could not be satisfied because - the frame could not be found.""" - -class NoSuchWindowException(WebDriverException): - """A request to switch to a different window could not be satisfied - because the window could not be found. - """ - -class ScriptTimeoutException(TimeoutException): - """A script did not complete before its timeout expired.""" - -class SessionNotCreatedException(WebDriverException): - """A new session could not be created.""" - -class StaleElementReferenceException(InvalidElementStateException): - """An element command failed because the referenced element is no - longer attached to the DOM. - """ - -class UnexpectedAlertOpenException(WebDriverException): - """A modal dialog was open, blocking this operation.""" - -class UnknownCommandException(WebDriverException): - """A command could not be executed because the remote end is not - aware of it. - """ - -class UnknownErrorException(WebDriverException): - """An unknown error occurred in the remote end while processing - the command. - """ - -class UnsupportedOperationException(WebDriverException): - """Indicates that a command that should have executed properly - cannot be supported for some reason. - """ - -class UnknownStatusCodeException(WebDriverException): - """Exception for all other status codes.""" - -_exceptions_strict = { - "element not selectable": ElementNotSelectableException, - "element not visible": ElementNotVisibleException, - "ime engine activation failed": ImeEngineActivationFailedException, - "ime not available": ImeNotAvailableException, - "invalid cookie domain": InvalidCookieDomainException, - "invalid element coordinates": InvalidElementCoordinatesException, - "invalid element state": InvalidElementStateException, - "invalid selector": InvalidSelectorException, - "javascript error": JavascriptErrorException, - "move target out of bounds": MoveTargetOutOfBoundsException, - "no such alert": NoSuchAlertException, - "no such element": NoSuchElementException, - "no such frame": NoSuchFrameException, - "no such window": NoSuchWindowException, - "script timeout": ScriptTimeoutException, - "session not created": SessionNotCreatedException, - "stale element reference": StaleElementReferenceException, - "success": None, - "timeout": TimeoutException, - "unable to set cookie": UnableToSetCookieException, - "unexpected alert open": UnexpectedAlertOpenException, - "unknown command": UnknownCommandException, - "unknown error": UnknownErrorException, - "unsupported operation": UnsupportedOperationException, -} - -_exceptions_compatibility = { - 15: ElementNotSelectableException, - 11: ElementNotVisibleException, - 31: ImeEngineActivationFailedException, - 30: ImeNotAvailableException, - 24: InvalidCookieDomainException, - 29: InvalidElementCoordinatesException, - 12: InvalidElementStateException, - 19: InvalidSelectorException, - 32: InvalidSelectorException, - 17: JavascriptErrorException, - 34: MoveTargetOutOfBoundsException, - 27: NoSuchAlertException, - 7: NoSuchElementException, - 8: NoSuchFrameException, - 23: NoSuchWindowException, - 28: ScriptTimeoutException, - 6: SessionNotCreatedException, - 33: SessionNotCreatedException, - 10: StaleElementReferenceException, - 0: None, # success - 21: TimeoutException, - 25: UnableToSetCookieException, - 26: UnexpectedAlertOpenException, - 9: UnknownCommandException, - 13: UnknownErrorException, - # "unsupported operation": UnsupportedOperationException -} diff --git a/webdriver/webdriver/keys.py b/webdriver/webdriver/keys.py deleted file mode 100644 index 9c6d93df821e9d..00000000000000 --- a/webdriver/webdriver/keys.py +++ /dev/null @@ -1,68 +0,0 @@ -"""Constants for special keys.""" - -class Keys: - """Constants for special keys.""" - NULL = '\uE000' - CANCEL = '\uE001' - HELP = '\uE002' - BACK_SPACE = '\uE003' - TAB = '\uE004' - CLEAR = '\uE005' - RETURN = '\uE006' - ENTER = '\uE007' - SHIFT = '\uE008' - LEFT_SHIFT = '\uE008' - CONTROL = '\uE009' - LEFT_CONTROL = '\uE009' - ALT = '\uE00A' - LEFT_ALT = '\uE00A' - PAUSE = '\uE00B' - ESCAPE = '\uE00C' - SPACE = '\uE00D' - PAGE_UP = '\uE00E' - PAGE_DOWN = '\uE00F' - END = '\uE010' - HOME = '\uE011' - LEFT = '\uE012' - ARROW_LEFT = '\uE012' - UP = '\uE013' - ARROW_UP = '\uE013' - RIGHT = '\uE014' - ARROW_RIGHT = '\uE014' - DOWN = '\uE015' - ARROW_DOWN = '\uE015' - INSERT = '\uE016' - DELETE = '\uE017' - SEMICOLON = '\uE018' - EQUALS = '\uE019' - NUMPAD0 = '\uE01A' - NUMPAD1 = '\uE01B' - NUMPAD2 = '\uE01C' - NUMPAD3 = '\uE01D' - NUMPAD4 = '\uE01E' - NUMPAD5 = '\uE01F' - NUMPAD6 = '\uE020' - NUMPAD7 = '\uE021' - NUMPAD8 = '\uE022' - NUMPAD9 = '\uE023' - MULTIPLY = '\uE024' - ADD = '\uE025' - SEPARATOR = '\uE026' - SUBTRACT = '\uE027' - DECIMAL = '\uE028' - DIVIDE = '\uE029' - F1 = '\uE031' - F2 = '\uE032' - F3 = '\uE033' - F4 = '\uE034' - F5 = '\uE035' - F6 = '\uE036' - F7 = '\uE037' - F8 = '\uE038' - F9 = '\uE039' - F10 = '\uE03A' - F11 = '\uE03B' - F12 = '\uE03C' - META = '\uE03D' - COMMAND = '\uE03D' - ZENKAKU_HANKAKU = '\uE040' diff --git a/webdriver/webdriver/searchcontext.py b/webdriver/webdriver/searchcontext.py deleted file mode 100644 index 061fa027db1a2c..00000000000000 --- a/webdriver/webdriver/searchcontext.py +++ /dev/null @@ -1,54 +0,0 @@ -"""WebDriver element location functionality.""" - -class SearchContext(object): - """Abstract class that provides the core element location functionality.""" - - def find_element_by_css(self, selector): - """Find the first element matching a css selector.""" - return self._find_element('css selector', selector) - - def find_elements_by_css(self, selector): - """Find all elements matching a css selector.""" - return self._find_elements('css selector', selector) - - def find_element_by_link_text(self, text): - """Find the first link with the given text.""" - return self._find_element('link text', text) - - def find_elements_by_link_text(self, text): - """Find all links with the given text.""" - return self._find_elements('link text', text) - - def find_element_by_partial_link_text(self, text): - """Find the first link containing the given text.""" - return self._find_element('partial link text', text) - - def find_elements_by_partial_link_text(self, text): - """Find all links containing the given text.""" - return self._find_elements('partial link text', text) - - def find_element_by_xpath(self, xpath): - """Find the first element matching the xpath.""" - return self._find_element('xpath', xpath) - - def find_elements_by_xpath(self, xpath): - """Find all elements matching the xpath.""" - return self._find_elements('xpath', xpath) - - def _find_element(self, strategy, value): - return self.execute('POST', - '/element', - 'findElement', - self._get_locator(strategy, value)) - - def _find_elements(self, strategy, value): - return self.execute('POST', - '/elements', - 'findElements', - self._get_locator(strategy, value)) - - def _get_locator(self, strategy, value): - if self.mode == 'strict': - return {'strategy': strategy, 'value': value} - elif self.mode == 'compatibility': - return {'using': strategy, 'value': value} diff --git a/webdriver/webdriver/wait.py b/webdriver/webdriver/wait.py deleted file mode 100644 index e93c42d1d720d7..00000000000000 --- a/webdriver/webdriver/wait.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright 2011 Software Freedom Conservancy. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Waiting functionality.""" - -import time -from exceptions import NoSuchElementException -from exceptions import TimeoutException - -POLL_FREQUENCY = 0.5 # How long to sleep inbetween calls to the method -IGNORED_EXCEPTIONS = [NoSuchElementException] # list of exceptions ignored during calls to the method - -class WebDriverWait(object): - - def __init__(self, driver, timeout, poll_frequency=POLL_FREQUENCY, ignored_exceptions=None): - """Constructor, takes a WebDriver instance and timeout in seconds. - - :Args: - - driver - Instance of WebDriver (Ie, Firefox, Chrome or Remote) - - timeout - Number of seconds before timing out - - poll_frequency - sleep interval between calls - By default, it is 0.5 second. - - ignored_exceptions - iterable structure of exception classes ignored during calls. - By default, it contains NoSuchElementException only. - - Example: - from selenium.webdriver.support.ui import WebDriverWait \n - element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("someId")) \n - is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).\ \n - until_not(lambda x: x.find_element_by_id("someId").is_displayed()) - """ - self._driver = driver - self._timeout = timeout - self._poll = poll_frequency - # avoid the divide by zero - if self._poll == 0: - self._poll = POLL_FREQUENCY - exceptions = IGNORED_EXCEPTIONS - if ignored_exceptions is not None: - try: - exceptions.extend(iter(ignored_exceptions)) - except TypeError: # ignored_exceptions is not iterable - exceptions.append(ignored_exceptions) - self._ignored_exceptions = tuple(exceptions) - - def until(self, method, message=''): - """Calls the method provided with the driver as an argument until the \ - return value is not False.""" - end_time = time.time() + self._timeout - while(True): - try: - value = method(self._driver) - if value: - return value - except self._ignored_exceptions: - pass - time.sleep(self._poll) - if(time.time() > end_time): - break - raise TimeoutException(message) - - def until_not(self, method, message=''): - """Calls the method provided with the driver as an argument until the \ - return value is False.""" - end_time = time.time() + self._timeout - while(True): - try: - value = method(self._driver) - if not value: - return value - except self._ignored_exceptions: - return True - time.sleep(self._poll) - if(time.time() > end_time): - break - raise TimeoutException(message) diff --git a/webdriver/webdriver/webelement.py b/webdriver/webdriver/webelement.py deleted file mode 100644 index 83e27f23116cc9..00000000000000 --- a/webdriver/webdriver/webelement.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Element-level WebDriver operations.""" - -import searchcontext - -class WebElement(searchcontext.SearchContext): - """Corresponds to a DOM element in the current page.""" - - def __init__(self, driver, id): - self._driver = driver - self._id = id - # Set value of mode used by SearchContext - self.mode = driver.mode - - def execute(self, method, path, name, body=None): - """Execute a command against this WebElement.""" - return self._driver.execute( - method, '/element/%s%s' % (self._id, path), name, body) - - def is_displayed(self): - """Is this element displayed?""" - return self.execute('GET', '/displayed', 'isDisplayed') - - def is_selected(self): - """Is this checkbox, radio button, or option selected?""" - return self.execute('GET', '/selected', 'isSelected') - - def get_attribute(self, name): - """Get the value of an element property or attribute.""" - return self.execute('GET', '/attribute/%s' % name, 'getElementAttribute') - - @property - def text(self): - """Get the visible text for this element.""" - return self.execute('GET', '/text', 'text') - - @property - def tag_name(self): - """Get the tag name for this element""" - return self.execute('GET', '/name', 'getElementTagName') - - def click(self): - """Click on this element.""" - return self.execute('POST', '/click', 'click') - - def clear(self): - """Clear the contents of the this text input.""" - self.execute('POST', '/clear', 'clear') - - def send_keys(self, keys): - """Send keys to this text input or body element.""" - if isinstance(keys, str): - keys = [keys] - self.execute('POST', '/value', 'sendKeys', {'value': keys}) - - def to_json(self): - return {'ELEMENT': self.id}