Skip to content

Commit

Permalink
[py] Add the ability to get and set timeouts against a driver. Fixes #…
Browse files Browse the repository at this point in the history
…7738

This adds in Get Timeouts command as described in https://w3c.github.io/webdriver/#get-timeouts
and cleans up the Set Timeouts command. A new Timeouts object has been
added to help guide people through this.
  • Loading branch information
AutomatedTester committed Feb 28, 2020
1 parent 24ab1e5 commit a849bb7
Show file tree
Hide file tree
Showing 5 changed files with 204 additions and 4 deletions.
94 changes: 94 additions & 0 deletions py/selenium/webdriver/common/timeouts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you 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.

class Timeouts(object):

def __init__(self, implicit_wait=None, page_load=None, script=None):
"""
Create a new Timeout object.
:Args:
- implicit_wait - Either an int or a float. The number passed in needs to how many
seconds the driver will wait.
- page_load - Either an int or a float. The number passed in needs to how many
seconds the driver will wait.
- script - Either an int or a float. The number passed in needs to how many
seconds the driver will wait.
"""
self._implicit_wait = self._convert(implicit_wait)
self._page_load = self._convert(page_load)
self._script = self._convert(script)

@property
def implicit_wait(self):
"""
Return the value for the implicit wait. This does not return the value on the remote end
"""
return self._implicit_wait / 1000

@implicit_wait.setter
def implicit_wait(self, _implicit_wait):
"""
Sets the value for the implicit wait. This does not set the value on the remote end
"""
self._implicit_wait = self._convert(_implicit_wait)

@property
def page_load(self):
"""
Return the value for the page load wait. This does not return the value on the remote end
"""
return self._page_load / 1000

@page_load.setter
def page_load(self, _page_load):
"""
Sets the value for the page load wait. This does not set the value on the remote end
"""
self._page_load = self._convert(_page_load)

@property
def script(self):
"""
Return the value for the script wait. This does not return the value on the remote end
"""
return self._script / 1000

@script.setter
def script(self, _script):
"""
Sets the value for the script wait. This does not set the value on the remote end
"""
self._script = self._convert(_script)

def _convert(self, timeout):
if timeout is not None:
if isinstance(timeout, (int, float)):
return int(float(timeout) * 1000)
else:
raise TypeError("Timeouts can only be an int or a float")

def _to_json(self):
timeouts = {}
if self._implicit_wait is not None:
timeouts["implicit"] = self._implicit_wait
if self._page_load is not None:
timeouts["pageLoad"] = self._page_load
if self._script is not None:
timeouts["script"] = self._script

return timeouts
1 change: 1 addition & 0 deletions py/selenium/webdriver/remote/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class Command(object):
EXECUTE_ASYNC_SCRIPT = "executeAsyncScript"
SET_SCRIPT_TIMEOUT = "setScriptTimeout"
SET_TIMEOUTS = "setTimeouts"
GET_TIMEOUTS = "getTimeouts"
MAXIMIZE_WINDOW = "windowMaximize"
W3C_MAXIMIZE_WINDOW = "w3cMaximizeWindow"
GET_LOG = "getLog"
Expand Down
2 changes: 2 additions & 0 deletions py/selenium/webdriver/remote/remote_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ def __init__(self, remote_server_addr, keep_alive=False, resolve_ip=None):
('POST', '/session/$sessionId/timeouts/async_script'),
Command.SET_TIMEOUTS:
('POST', '/session/$sessionId/timeouts'),
Command.GET_TIMEOUTS:
('GET', '/session/$sessionId/timeouts'),
Command.DISMISS_ALERT:
('POST', '/session/$sessionId/dismiss_alert'),
Command.W3C_DISMISS_ALERT:
Expand Down
41 changes: 37 additions & 4 deletions py/selenium/webdriver/remote/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,22 @@
import warnings

from .command import Command
from .webelement import WebElement
from .remote_connection import RemoteConnection
from .errorhandler import ErrorHandler
from .switch_to import SwitchTo
from .mobile import Mobile
from .file_detector import FileDetector, LocalFileDetector
from .mobile import Mobile
from .remote_connection import RemoteConnection
from .switch_to import SwitchTo
from .webelement import WebElement

from selenium.common.exceptions import (InvalidArgumentException,
WebDriverException,
NoSuchCookieException,
UnknownMethodException)
from selenium.webdriver.common.by import By
from selenium.webdriver.common.html5.application_cache import ApplicationCache

from selenium.webdriver.common.timeouts import Timeouts

from selenium.webdriver.support.relative_locator import RelativeBy

try:
Expand Down Expand Up @@ -1002,6 +1005,36 @@ def set_page_load_timeout(self, time_to_wait):
'ms': float(time_to_wait) * 1000,
'type': 'page load'})

@property
def timeouts(self):
"""
Get all the timeouts that have been set on the current session
:Usage:
::
driver.timeouts
:rtype: Timeout
"""
timeouts = self.execute(Command.GET_TIMEOUTS)['value']
timeouts["implicit_wait"] = timeouts.pop("implicit") / 1000
timeouts["page_load"] = timeouts.pop("pageLoad") / 1000
timeouts["script"] = timeouts.pop("script") / 1000
return Timeouts(**timeouts)

@timeouts.setter
def timeouts(self, timeouts):
"""
Set all timeouts for the session. This will override any previously
set timeouts.
:Usage:
::
my_timeouts = Timeouts()
my_timeouts.implicit_wait = 10
driver.timeouts = my_timeouts
"""
self.execute(Command.SET_TIMEOUTS, timeouts._to_json())['value']

def find_element(self, by=By.ID, value=None):
"""
Find an element given a By strategy and locator. Prefer the find_element_by_* methods when
Expand Down
70 changes: 70 additions & 0 deletions py/test/selenium/webdriver/common/timeout_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The SFC licenses this file
# to you 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.


import pytest

from selenium.webdriver.common.timeouts import Timeouts

def test_should_create_timeouts_object():
implicit_wait = 10
page_load = 10
script = 10
timeouts = Timeouts(implicit_wait=implicit_wait,page_load=page_load,script=script)

assert implicit_wait == timeouts.implicit_wait
assert page_load == timeouts.page_load
assert script == timeouts.script

def test_should_error_if_implicit_wait_isnt_a_number():
with pytest.raises(TypeError):
Timeouts(implicit_wait="abc")

timeout = Timeouts(implicit_wait=0)
with pytest.raises(TypeError):
timeout.implicit_wait="abc"


def test_should_error_if_page_load_isnt_a_number():
with pytest.raises(TypeError):
Timeouts(page_load="abc")

timeout = Timeouts(page_load=0)
with pytest.raises(TypeError):
timeout.page_load = "abc"


def test_should_error_if_script_isnt_a_number():
with pytest.raises(TypeError):
Timeouts(script="abc")

timeout = Timeouts(script=0)
with pytest.raises(TypeError):
timeout.script = "abc"


def test_should_get_timeouts_without_setting_them(driver):
results = driver.timeouts
assert results.implicit_wait == 0
assert results.page_load == 300
assert results.script == 30

def test_should_set_and_get_timeouts_on_remote_end(driver):
timeout = Timeouts(implicit_wait=10)
driver.timeouts = timeout
result = driver.timeouts
assert result.implicit_wait == timeout.implicit_wait

0 comments on commit a849bb7

Please sign in to comment.