diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py
index bbb2b4757..ddd0acc47 100644
--- a/src/SeleniumLibrary/__init__.py
+++ b/src/SeleniumLibrary/__init__.py
@@ -25,6 +25,7 @@
CookieKeywords,
ElementKeywords,
FormElementKeywords,
+ FrameKeywords,
JavaScriptKeywords,
RunOnFailureKeywords,
ScreenshotKeywords,
@@ -64,10 +65,10 @@ class SeleniumLibrary(DynamicCore):
= Locating elements =
All keywords in SeleniumLibrary that need to interact with an element
- on a web page take an argument named ``locator`` that specifies how
- to find the element. Most often the locator is given as a string using
- the locator syntax described below, but `using WebElements` is possible
- too.
+ on a web page take an argument typically named ``locator`` that specifies
+ how to find the element. Most often the locator is given as a string
+ using the locator syntax described below, but `using WebElements` is
+ possible too.
== Locator syntax ==
@@ -100,7 +101,7 @@ class SeleniumLibrary(DynamicCore):
| `Click Element` | name:foo | # Find element with name ``foo``. |
| `Click Element` | default:name:foo | # Use default strategy with value ``name:foo``. |
| `Click Element` | //foo | # Find element using XPath ``//foo``. |
- | `Click Element` | default://foo | # Use default strategy with value ``//foo``. |
+ | `Click Element` | default: //foo | # Use default strategy with value ``//foo``. |
=== Explicit locator strategy ===
@@ -108,9 +109,9 @@ class SeleniumLibrary(DynamicCore):
syntax ``strategy:value`` or ``strategy=value``. The former syntax
is preferred, because the latter is identical to Robot Framework's
[http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#named-argument-syntax|
- named argument syntax] and that can cause problems. Notice that the
- ``strategy:value`` syntax is olny supported by SeleniumLibrary 3.0 and
- newer, though.
+ named argument syntax] and that can cause problems. Spaces around
+ the separator are ignored, so ``id:foo``, ``id: foo`` and ``id : foo``
+ are all equivalent.
Locator strategies that are supported by default are listed in the table
below. In addition to them, it is possible to register `custom locators`.
@@ -135,20 +136,33 @@ class SeleniumLibrary(DynamicCore):
prefix is only necessary if the locator value itself accidentally
matches some of the explicit strategies.
- Spaces around the separator are ignored, so ``id:foo``, ``id: foo``
- and ``id : foo`` are all equivalent.
+ Different locator strategies have different pros and cons. Using ids,
+ either explicitly like ``id:foo`` or by using the `default locator
+ strategy` simply like ``foo``, is recommended when possible, because
+ the syntax is simple and locating elements by an id is fast for browsers.
+ If an element does not have an id or the id is not stable, other
+ solutions need to be used. If an element has a unique tag name or class,
+ using ``tag``, ``class`` or ``css`` strategy like ``tag:h1``,
+ ``class:example`` or ``css:h1.example`` is often an easy solution. In
+ more complex cases using XPath expressions is typically the best
+ approach. They are very powerful but a downside is that they can also
+ get complex.
Examples:
- | `Click Element` | id:container |
- | `Click Element` | css:div#container h1 |
- | `Click Element` | xpath: //div[@id="container"]//h1 |
+ | `Click Element` | id:foo | # Element with id 'foo'. |
+ | `Click Element` | css:div#foo h1 | # h1 element under div with id 'foo'. |
+ | `Click Element` | xpath: //div[@id="foo"]//h1 | # Same as the above using XPath, not CSS. |
+ | `Click Element` | xpath: //*[contains(text(), "example")] | # Element containing text 'example'. |
- Notice that using the ``sizzle`` strategy or its alias ``jquery``
- requires that the system under test contains the jQuery library.
+ *NOTE:*
- Notice also that prior to SeleniumLibrary 3.0, table related keywords
- only supported ``xpath``, ``css`` and ``sizzle/jquery`` strategies.
+ - The ``strategy:value`` syntax is only supported by SeleniumLibrary 3.0
+ and newer.
+ - Using the ``sizzle`` strategy or its alias ``jquery`` requires that
+ the system under test contains the jQuery library.
+ - Prior to SeleniumLibrary 3.0, table related keywords only supported
+ ``xpath``, ``css`` and ``sizzle/jquery`` strategies.
=== Implicit XPath strategy ===
@@ -158,8 +172,8 @@ class SeleniumLibrary(DynamicCore):
Examples:
- | `Click Element` | //div[@id="container"] |
- | `Click Element` | (//div)[2] |
+ | `Click Element` | //div[@id="foo"]//h1 |
+ | `Click Element` | (//div)[2] |
The support for the ``(//`` prefix is new in SeleniumLibrary 3.0.
@@ -316,14 +330,15 @@ def __init__(self, timeout=5.0, implicit_wait=0.0,
libraries = [
AlertKeywords(self),
BrowserManagementKeywords(self),
- RunOnFailureKeywords(self),
+ CookieKeywords(self),
ElementKeywords(self),
- TableElementKeywords(self),
FormElementKeywords(self),
- SelectElementKeywords(self),
+ FrameKeywords(self),
JavaScriptKeywords(self),
- CookieKeywords(self),
+ RunOnFailureKeywords(self),
ScreenshotKeywords(self),
+ SelectElementKeywords(self),
+ TableElementKeywords(self),
WaitingKeywords(self)
]
self._browsers = BrowserCache()
diff --git a/src/SeleniumLibrary/base/context.py b/src/SeleniumLibrary/base/context.py
index 52e16e160..061d1ed75 100644
--- a/src/SeleniumLibrary/base/context.py
+++ b/src/SeleniumLibrary/base/context.py
@@ -14,6 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from SeleniumLibrary.utils import escape_xpath_value
+
class ContextAware(object):
@@ -37,11 +39,46 @@ def browsers(self):
def element_finder(self):
return self.ctx.element_finder
+ @property
+ def table_element_finder(self):
+ return self.ctx.table_element_finder
+
def find_element(self, locator, tag=None, first_only=True, required=True,
parent=None):
+ """Find element matching `locator`.
+
+ :param locator: Locator to use when searching the element.
+ See library documentation for the supported locator syntax.
+ :param tag: Limit searching only to these elements.
+ :param first_only: Return only first matching element if true,
+ a list of elements otherwise.
+ :param required: Raise `ElementNotFound` if element not found when
+ true, return `None` otherwise.
+ :param parent: Possible parent `WebElememt` element to search
+ elements from. By default search starts from `WebDriver`.
+ :return: Found `WebElement` or `None` if element not found and
+ `required` is false.
+ :rtype: selenium.webdriver.remote.webelement.WebElement
+ :raises SeleniumLibrary.errors.ElementNotFound: If element not found
+ and `required` is true.
+ """
return self.element_finder.find(locator, tag, first_only,
required, parent)
- @property
- def table_element_finder(self):
- return self.ctx.table_element_finder
+ def find_elements(self, locator, tag=None, parent=None):
+ """Find all elements matching `locator`.
+
+ Always returns a list of `WebElement` objects. If no matching element
+ is found, the list is empty. Otherwise semantics are exactly same
+ as with :meth:`find_element`.
+ """
+ return self.find_element(locator, tag, False, False, parent)
+
+ def is_text_present(self, text):
+ locator = "xpath://*[contains(., %s)]" % escape_xpath_value(text)
+ return self.find_element(locator, required=False) is not None
+
+ def is_element_enabled(self, locator, tag=None):
+ element = self.find_element(locator, tag)
+ return (element.is_enabled() and
+ element.get_attribute('readonly') is None)
diff --git a/src/SeleniumLibrary/base/librarycomponent.py b/src/SeleniumLibrary/base/librarycomponent.py
index 1273fe366..b3e8d4795 100644
--- a/src/SeleniumLibrary/base/librarycomponent.py
+++ b/src/SeleniumLibrary/base/librarycomponent.py
@@ -25,14 +25,8 @@
from .robotlibcore import PY2
-LOG_LEVELS = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR']
-
-
class LibraryComponent(ContextAware):
- def __init__(self, ctx):
- ContextAware.__init__(self, ctx)
-
def info(self, msg, html=False):
logger.info(msg, html)
@@ -40,21 +34,36 @@ def debug(self, msg, html=False):
logger.debug(msg, html)
def log(self, msg, level='INFO', html=False):
- if level.upper() in LOG_LEVELS:
- logger.write(msg, level, html)
+ if not is_noney(level):
+ logger.write(msg, level.upper(), html)
def warn(self, msg, html=False):
logger.warn(msg, html)
+ def log_source(self, loglevel='INFO'):
+ self.ctx.log_source(loglevel)
+
def assert_page_contains(self, locator, tag=None, message=None,
loglevel='INFO'):
- self.element_finder.assert_page_contains(locator, tag, message,
- loglevel)
+ if not self.find_element(locator, tag, required=False):
+ self.log_source(loglevel)
+ if is_noney(message):
+ message = ("Page should have contained %s '%s' but did not."
+ % (tag or 'element', locator))
+ raise AssertionError(message)
+ logger.info("Current page contains %s '%s'."
+ % (tag or 'element', locator))
def assert_page_not_contains(self, locator, tag=None, message=None,
loglevel='INFO'):
- self.element_finder.assert_page_not_contains(locator, tag, message,
- loglevel)
+ if self.find_element(locator, tag, required=False):
+ self.log_source(loglevel)
+ if is_noney(message):
+ message = ("Page should not have contained %s '%s'."
+ % (tag or 'element', locator))
+ raise AssertionError(message)
+ logger.info("Current page does not contain %s '%s'."
+ % (tag or 'element', locator))
def get_timeout(self, timeout=None):
if is_noney(timeout):
diff --git a/src/SeleniumLibrary/errors.py b/src/SeleniumLibrary/errors.py
new file mode 100644
index 000000000..8217f34ec
--- /dev/null
+++ b/src/SeleniumLibrary/errors.py
@@ -0,0 +1,23 @@
+# Copyright 2008-2011 Nokia Networks
+# Copyright 2011-2016 Ryan Tomac, Ed Manlove and contributors
+# Copyright 2016- Robot Framework Foundation
+#
+# 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.
+
+
+class SeleniumLibraryException(Exception):
+ ROBOT_SUPPRESS_NAME = True
+
+
+class ElementNotFound(SeleniumLibraryException):
+ pass
diff --git a/src/SeleniumLibrary/keywords/__init__.py b/src/SeleniumLibrary/keywords/__init__.py
index 19a67584a..5776bc2a1 100644
--- a/src/SeleniumLibrary/keywords/__init__.py
+++ b/src/SeleniumLibrary/keywords/__init__.py
@@ -19,6 +19,7 @@
from .cookie import CookieKeywords
from .element import ElementKeywords
from .formelement import FormElementKeywords
+from .frames import FrameKeywords
from .javascript import JavaScriptKeywords
from .runonfailure import RunOnFailureKeywords
from .screenshot import ScreenshotKeywords
diff --git a/src/SeleniumLibrary/keywords/browsermanagement.py b/src/SeleniumLibrary/keywords/browsermanagement.py
index 327f573ba..1bb0e73b4 100644
--- a/src/SeleniumLibrary/keywords/browsermanagement.py
+++ b/src/SeleniumLibrary/keywords/browsermanagement.py
@@ -18,7 +18,6 @@
import time
import types
-from robot.errors import DataError
from robot.utils import NormalizedDict
from selenium import webdriver
from selenium.common.exceptions import NoSuchWindowException
@@ -328,27 +327,6 @@ def set_window_position(self, x, y):
"""
self.browser.set_window_position(int(x), int(y))
- @keyword
- def select_frame(self, locator):
- """Sets frame identified by ``locator`` as the current frame.
-
- Key attributes for frames are `id` and `name.` See `introduction` for
- details about locating elements.
-
- See `Unselect Frame` to cancel the frame selection and return to the Main frame.
-
- Please note that the frame search always start from the document root or main frame.
-
- Example:
- | Select Frame | xpath: //frame[@name='top]/iframe[@name='left'] | # Selects the 'left' iframe |
- | Click Link | foo | # Clicks link 'foo' in 'left' iframe |
- | Unselect Frame | | # Returns to main frame |
- | Select Frame | left | # Selects the 'top' frame |
- """
- self.info("Selecting frame '%s'." % locator)
- element = self.find_element(locator)
- self.browser.switch_to.frame(element)
-
@keyword
def select_window(self, locator=None):
"""Selects the window matching locator and return previous window handle.
@@ -396,14 +374,6 @@ def list_windows(self):
"""Return all current window handles as a list."""
return self.browser.window_handles
- @keyword
- def unselect_frame(self):
- """Sets the top frame as the current frame.
-
- In practice cancels a previous `Select Frame` call.
- """
- self.browser.switch_to.default_content()
-
@keyword
def get_location(self):
"""Returns the current browser URL."""
@@ -431,8 +401,8 @@ def location_should_be(self, url):
"""Verifies that current URL is exactly ``url``."""
actual = self.get_location()
if actual != url:
- raise AssertionError("Location should have been '%s' but was '%s'"
- % (url, actual))
+ raise AssertionError("Location should have been '%s' but was "
+ "'%s'." % (url, actual))
self.info("Current location is '%s'." % url)
@keyword
@@ -460,7 +430,7 @@ def log_source(self, loglevel='INFO'):
(no logging).
"""
source = self.get_source()
- self.log(source, loglevel.upper())
+ self.log(source, loglevel)
return source
@keyword
diff --git a/src/SeleniumLibrary/keywords/element.py b/src/SeleniumLibrary/keywords/element.py
index fb29e7958..237b8a4f7 100644
--- a/src/SeleniumLibrary/keywords/element.py
+++ b/src/SeleniumLibrary/keywords/element.py
@@ -18,240 +18,206 @@
from selenium.webdriver.common.keys import Keys
from SeleniumLibrary.base import LibraryComponent, keyword
-from SeleniumLibrary.keywords.formelement import FormElementKeywords
-from SeleniumLibrary.utils import escape_xpath_value, is_falsy, is_truthy
+from SeleniumLibrary.utils import (is_falsy, is_noney, is_truthy,
+ plural_or_not as s)
class ElementKeywords(LibraryComponent):
- def __init__(self, ctx):
- LibraryComponent.__init__(self, ctx)
- self.form_element = FormElementKeywords(ctx)
-
@keyword
def get_webelement(self, locator):
- """Returns the first WebElement matching the given locator.
+ """Returns the first WebElement matching the given ``locator``.
- See `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
return self.find_element(locator)
@keyword
def get_webelements(self, locator):
- """Returns list of WebElement objects matching locator.
-
- See `introduction` for details about locating elements.
-
- New in SeleniumLibrary 3.0.0: If element is not found, keyword
- does not anymore fail. In previous releases keyword did fail if
- element is not found.
- """
- return self.find_element(locator, first_only=False, required=False)
-
- @keyword
- def current_frame_should_contain(self, text, loglevel='INFO'):
- """Verifies that current frame contains `text`.
-
- See `Page Should Contain ` for explanation about `loglevel` argument.
-
- Prior to SeleniumLibrary 3.0 this keyword was named
- `Current Frame Contains`.
- """
- if not self.is_text_present(text):
- self.ctx.log_source(loglevel)
- raise AssertionError("Page should have contained text '%s' "
- "but did not" % text)
- self.info("Current page contains text '%s'." % text)
-
- @keyword
- def current_frame_contains(self, text, loglevel='INFO'):
- """Deprecated. Use `Current Frame Should Contain` instead."""
- self.current_frame_should_contain(text, loglevel)
+ """Returns list of WebElement objects matching the ``locator``.
- @keyword
- def current_frame_should_not_contain(self, text, loglevel='INFO'):
- """Verifies that current frame contains `text`.
+ See the `Locating elements` section for details about the locator
+ syntax.
- See `Page Should Contain ` for explanation about `loglevel` argument.
+ Starting from SeleniumLibrary 3.0, the keyword returns an empty
+ list if there are no matching elements. In previous releases the
+ keyword failed in this case.
"""
- if self.is_text_present(text):
- self.ctx.log_source(loglevel)
- raise AssertionError("Page should not have contained text '%s' "
- "but it did" % text)
- self.info("Current page should not contain text '%s'." % text)
+ return self.find_elements(locator)
@keyword
- def element_should_contain(self, locator, expected, message=''):
- """Verifies element identified by `locator` contains text `expected`.
+ def element_should_contain(self, locator, expected, message=None):
+ """Verifies that element ``locator`` contains text ``expected``.
- If you wish to assert an exact (not a substring) match on the text
- of the element, use `Element Text Should Be`.
+ See the `Locating elements` section for details about the locator
+ syntax.
- `message` can be used to override the default error message.
+ The ``message`` argument can be used to override the default error
+ message.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ Use `Element Text Should Be` if you want to match the exact text,
+ not a substring.
"""
- self.info("Verifying element '%s' contains "
- "text '%s'." % (locator, expected))
- actual = self._get_text(locator)
+ actual = self.find_element(locator).text
if expected not in actual:
- if is_falsy(message):
+ if is_noney(message):
message = "Element '%s' should have contained text '%s' but "\
"its text was '%s'." % (locator, expected, actual)
raise AssertionError(message)
+ self.info("Element '%s' contains text '%s'." % (locator, expected))
@keyword
- def element_should_not_contain(self, locator, expected, message=''):
- """Verifies element identified by `locator` does not contain text `expected`.
+ def element_should_not_contain(self, locator, expected, message=None):
+ """Verifies that element ``locator`` does not contains text ``expected``.
- `message` can be used to override the default error message.
+ See the `Locating elements` section for details about the locator
+ syntax.
- Key attributes for arbitrary elements are `id` and `name`. See
- `Element Should Contain` for more details.
+ The ``message`` argument can be used to override the default error
+ message.
"""
- self.info("Verifying element '%s' does not contain text '%s'."
- % (locator, expected))
- actual = self._get_text(locator)
+ actual = self.find_element(locator).text
if expected in actual:
- if is_falsy(message):
+ if is_noney(message):
message = "Element '%s' should not contain text '%s' but " \
"it did." % (locator, expected)
raise AssertionError(message)
-
- @keyword
- def frame_should_contain(self, locator, text, loglevel='INFO'):
- """Verifies frame identified by `locator` contains `text`.
-
- See `Page Should Contain ` for explanation about `loglevel` argument.
-
- Key attributes for frames are `id` and `name.` See `introduction` for
- details about locating elements.
- """
- if not self._frame_contains(locator, text):
- self.ctx.log_source(loglevel)
- raise AssertionError("Page should have contained text '%s' "
- "but did not" % text)
- self.info("Current page contains text '%s'." % text)
+ self.info("Element '%s' does not contain text '%s'."
+ % (locator, expected))
@keyword
def page_should_contain(self, text, loglevel='INFO'):
- """Verifies that current page contains `text`.
+ """Verifies that current page contains ``text``.
If this keyword fails, it automatically logs the page source
- using the log level specified with the optional `loglevel` argument.
- Valid log levels are DEBUG, INFO (default), WARN, and NONE. If the
- log level is NONE or below the current active log level the source
- will not be logged.
+ using the log level specified with the optional ``loglevel``
+ argument. Valid log levels are ``DEBUG``, ``INFO`` (default),
+ ``WARN``, and ``NONE``. If the log level is ``NONE`` or below
+ the current active log level the source will not be logged.
"""
if not self._page_contains(text):
self.ctx.log_source(loglevel)
raise AssertionError("Page should have contained text '%s' "
- "but did not" % text)
+ "but did not." % text)
self.info("Current page contains text '%s'." % text)
@keyword
- def page_should_contain_element(self, locator, message='', loglevel='INFO'):
- """Verifies element identified by `locator` is found on the current page.
+ def page_should_contain_element(self, locator, message=None, loglevel='INFO'):
+ """Verifies that element ``locator`` is found on the current page.
- `message` can be used to override default error message.
+ See the `Locating elements` section for details about the locator
+ syntax.
- See `Page Should Contain` for explanation about `loglevel` argument.
+ The ``message`` argument can be used to override the default error
+ message.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See `Page Should Contain` for explanation about the ``loglevel``
+ argument.
"""
self.assert_page_contains(locator, message=message, loglevel=loglevel)
@keyword
- def locator_should_match_x_times(self, locator, expected_locator_count, message='', loglevel='INFO'):
- """Verifies that the page contains the given number of elements located by the given `locator`.
+ def locator_should_match_x_times(self, locator, x, message=None, loglevel='INFO'):
+ """Verifies that ``locator`` matches ``x`` number of elements.
- See `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
- See `Page Should Contain Element` for explanation about `message` and
- `loglevel` arguments.
+ See `Page Should Contain Element` for explanation about ``message``
+ and ``loglevel`` arguments.
"""
- actual_locator_count = len(self.find_element(
- locator, first_only=False, required=False)
- )
- if int(actual_locator_count) != int(expected_locator_count):
+ count = len(self.find_elements(locator))
+ x = int(x)
+ if count != x:
if is_falsy(message):
- message = "Locator %s should have matched %s times but matched %s times"\
- %(locator, expected_locator_count, actual_locator_count)
+ message = ("Locator '%s' should have matched %s time%s but "
+ "matched %s time%s."
+ % (locator, x, s(x), count, s(count)))
self.ctx.log_source(loglevel)
raise AssertionError(message)
self.info("Current page contains %s elements matching '%s'."
- % (actual_locator_count, locator))
+ % (count, locator))
@keyword
def page_should_not_contain(self, text, loglevel='INFO'):
- """Verifies the current page does not contain `text`.
+ """Verifies the current page does not contain ``text``.
- See `Page Should Contain ` for explanation about `loglevel` argument.
+ See `Page Should Contain` for explanation about the ``loglevel``
+ argument.
"""
if self._page_contains(text):
self.ctx.log_source(loglevel)
- raise AssertionError("Page should not have contained text '%s'" % text)
+ raise AssertionError("Page should not have contained text '%s'."
+ % text)
self.info("Current page does not contain text '%s'." % text)
@keyword
- def page_should_not_contain_element(self, locator, message='', loglevel='INFO'):
- """Verifies element identified by `locator` is not found on the current page.
-
- `message` can be used to override the default error message.
+ def page_should_not_contain_element(self, locator, message=None, loglevel='INFO'):
+ """Verifies that element ``locator`` is found on the current page.
- See `Page Should Contain ` for explanation about `loglevel` argument.
+ See the `Locating elements` section for details about the locator
+ syntax.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See `Page Should Contain` for explanation about ``message`` and
+ ``loglevel`` arguments.
"""
self.assert_page_not_contains(locator, message=message,
loglevel=loglevel)
@keyword
def assign_id_to_element(self, locator, id):
- """Assigns a temporary identifier to element specified by `locator`.
+ """Assigns temporary ``id`` to element specified by ``locator``.
- This is mainly useful if the locator is complicated/slow XPath expression.
- Identifier expires when the page is reloaded.
+ This is mainly useful if the locator is complicated and/or slow XPath
+ expression and it is needed multiple times. Identifier expires when
+ the page is reloaded.
+
+ See the `Locating elements` section for details about the locator
+ syntax.
Example:
- | Assign ID to Element | xpath=//div[@id="first_div"] | my id |
- | Page Should Contain Element | my id |
+ | `Assign ID to Element` | //ul[@class='example' and ./li[contains(., 'Stuff')]] | my id |
+ | `Page Should Contain Element` | my id |
"""
- self.info("Assigning temporary id '%s' to element '%s'" % (id, locator))
+ self.info("Assigning temporary id '%s' to element '%s'." % (id, locator))
element = self.find_element(locator)
self.browser.execute_script("arguments[0].id = '%s';" % id, element)
@keyword
def element_should_be_disabled(self, locator):
- """Verifies that element identified with `locator` is disabled.
+ """Verifies that element identified with ``locator`` is disabled.
+
+ This keyword considers also elements that are read-only to be
+ disabled.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- if self._is_enabled(locator):
- raise AssertionError("Element '%s' is enabled." % (locator))
+ if self.is_element_enabled(locator):
+ raise AssertionError("Element '%s' is enabled." % locator)
@keyword
def element_should_be_enabled(self, locator):
- """Verifies that element identified with `locator` is enabled.
+ """Verifies that element identified with ``locator`` is enabled.
+
+ This keyword considers also elements that are read-only to be
+ disabled.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- if not self._is_enabled(locator):
- raise AssertionError("Element '%s' is disabled." % (locator))
+ if not self.is_element_enabled(locator):
+ raise AssertionError("Element '%s' is disabled." % locator)
@keyword
def element_should_be_focused(self, locator):
- """Verifies that element identified with `locator` is focused.
+ """Verifies that element identified with ``locator`` is focused.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
- New in SeleniumLibrary 3.0.0.
+ New in SeleniumLibrary 3.0.
"""
element = self.find_element(locator)
if self.browser.capabilities['browserName'] != "firefox":
@@ -259,187 +225,182 @@ def element_should_be_focused(self, locator):
else:
focused = self.browser.execute_script('return document.activeElement;')
if element != focused:
- raise AssertionError("Element '%s' is not with focus." % (locator))
+ raise AssertionError("Element '%s' does not have focus." % locator)
@keyword
- def element_should_be_visible(self, locator, message=''):
- """Verifies that the element identified by `locator` is visible.
+ def element_should_be_visible(self, locator, message=None):
+ """Verifies that the element identified by ``locator`` is visible.
- Herein, visible means that the element is logically visible, not optically
- visible in the current browser viewport. For example, an element that carries
- display:none is not logically visible, so using this keyword on that element
- would fail.
+ Herein, visible means that the element is logically visible, not
+ optically visible in the current browser viewport. For example,
+ an element that carries ``display:none`` is not logically visible,
+ so using this keyword on that element would fail.
- `message` can be used to override the default error message.
+ See the `Locating elements` section for details about the locator
+ syntax.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ The ``message`` argument can be used to override the default error
+ message.
"""
- self.info("Verifying element '%s' is visible." % locator)
- visible = self.is_visible(locator)
- if not visible:
- if is_falsy(message):
+ if not self.find_element(locator).is_displayed():
+ if is_noney(message):
message = ("The element '%s' should be visible, but it "
"is not." % locator)
raise AssertionError(message)
+ self.info("Element '%s' is displayed." % locator)
@keyword
- def element_should_not_be_visible(self, locator, message=''):
- """Verifies that the element identified by `locator` is NOT visible.
-
- This is the opposite of `Element Should Be Visible`.
+ def element_should_not_be_visible(self, locator, message=None):
+ """Verifies that the element identified by ``locator`` is NOT visible.
- `message` can be used to override the default error message.
-
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ Passes if element does not exists. See `Element Should Be Visible`
+ for more information about visibility and supported arguments.
"""
- self.info("Verifying element '%s' is not visible." % locator)
- visible = self.is_visible(locator)
- if visible:
- if is_falsy(message):
+ element = self.find_element(locator, required=False)
+ if element is None:
+ self.info("Element '%s' did not exist." % locator)
+ elif not element.is_displayed():
+ self.info("Element '%s' exists but is not displayed." % locator)
+ else:
+ if is_noney(message):
message = ("The element '%s' should not be visible, "
"but it is." % locator)
raise AssertionError(message)
@keyword
- def element_text_should_be(self, locator, expected, message=''):
- """Verifies element identified by `locator` exactly contains text `expected`.
+ def element_text_should_be(self, locator, expected, message=None):
+ """Verifies that element ``locator`` contains exact text ``expected``.
- In contrast to `Element Should Contain`, this keyword does not try
- a substring match but an exact match on the element identified by `locator`.
+ See the `Locating elements` section for details about the locator
+ syntax.
- `message` can be used to override the default error message.
+ The ``message`` argument can be used to override the default error
+ message.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ Use `Element Should Contain` if a substring match is desired.
"""
- self.info("Verifying element '%s' contains exactly text '%s'."
+ self.info("Verifying element '%s' contains exact text '%s'."
% (locator, expected))
- element = self.find_element(locator)
- actual = element.text
- if expected != actual:
- if is_falsy(message):
+ text = self.find_element(locator).text
+ if text != expected:
+ if is_noney(message):
message = ("The text of element '%s' should have been '%s' "
- "but in fact it was '%s'."
- % (locator, expected, actual))
+ "but it was '%s'."
+ % (locator, expected, text))
raise AssertionError(message)
@keyword
- def get_element_attribute(self, locator, attribute_name=None):
- """Returns value of the element attribute.
+ def get_element_attribute(self, locator, attribute=None):
+ """Returns value of ``attribute`` from element ``locator``.
- There are two cases how to use this keyword.
-
- First, if only `locator` is provided, `locator` should consists of
- element locator followed by an @ sign and attribute name.
- This behavior is left for backward compatibility.
+ See the `Locating elements` section for details about the locator
+ syntax.
Example:
- | ${id}= | Get Element Attribute | link=Link with id@id |
-
- Second, if `locator` and `attribute_name` are provided both, `locator`
- should be standard locator and `attribute_name` is name of the
- requested element attribute.
+ | ${id}= | `Get Element Attribute` | css:h1 | id |
- Examples:
- | ${id}= | Get Element Attribute | link=Link with id | id |
- | ${element_by_dom}= | Get Webelement | dom=document.getElementsByTagName('a')[3] |
- | ${id}= | Get Element Attribute | ${element_by_dom} | id |
+ Passing attribute name as part of the ``locator`` is deprecated
+ since SeleniumLibrary 3.0. The explicit ``attribute`` argument
+ should be used instead.
"""
- if is_falsy(attribute_name):
- locator, attribute_name = self._parse_attribute_locator(locator)
- element = self.find_element(locator, required=False)
- if not element:
- raise ValueError("Element '%s' not found." % (locator))
- return element.get_attribute(attribute_name)
+ if is_noney(attribute):
+ self.warn("Using 'Get Element Attribute' without explicit "
+ "attribute is deprecated.")
+ locator, attribute = locator.rsplit('@', 1)
+ return self.find_element(locator).get_attribute(attribute)
@keyword
def get_horizontal_position(self, locator):
- """Returns horizontal position of element identified by `locator`.
+ """Returns horizontal position of element identified by ``locator``.
+
+ See the `Locating elements` section for details about the locator
+ syntax.
The position is returned in pixels off the left side of the page,
- as an integer. Fails if a matching element is not found.
+ as an integer.
See also `Get Vertical Position`.
"""
- element = self.find_element(locator, required=False)
- if not element:
- raise AssertionError("Could not determine position for '%s'"
- % locator)
- return element.location['x']
+ return self.find_element(locator).location['x']
@keyword
def get_element_size(self, locator):
- """Returns width and height of element identified by `locator`.
+ """Returns width and height of element identified by ``locator``.
+
+ See the `Locating elements` section for details about the locator
+ syntax.
- The element width and height is returned.
- Fails if a matching element is not found.
+ Both width and height are returned as integers.
+
+ Example:
+ | ${width} | ${height} = | `Get Element Size` | css:div#container |
"""
element = self.find_element(locator)
return element.size['width'], element.size['height']
@keyword
def get_value(self, locator):
- """Returns the value attribute of element identified by `locator`.
+ """Returns the value attribute of element identified by ``locator``.
- See `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- return self.ctx.element_finder.get_value(locator)
+ return self.get_element_attribute(locator, 'value')
@keyword
def get_text(self, locator):
- """Returns the text value of element identified by `locator`.
+ """Returns the text value of element identified by ``locator``.
- See `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- return self._get_text(locator)
+ return self.find_element(locator).text
@keyword
def clear_element_text(self, locator):
- """Clears the text value of text entry element identified by `locator`.
+ """Clears the value of text entry element identified by ``locator``.
- See `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- element = self.find_element(locator)
- element.clear()
+ self.find_element(locator).clear()
@keyword
def get_vertical_position(self, locator):
- """Returns vertical position of element identified by `locator`.
+ """Returns vertical position of element identified by ``locator``.
+
+ See the `Locating elements` section for details about the locator
+ syntax.
The position is returned in pixels off the top of the page,
- as an integer. Fails if a matching element is not found.
+ as an integer.
See also `Get Horizontal Position`.
"""
- element = self.find_element(locator, required=False)
- if element is None:
- raise AssertionError("Could not determine position for '%s'"
- % locator)
- return element.location['y']
+ return self.find_element(locator).location['y']
@keyword
def click_element(self, locator):
- """Click element identified by `locator`.
+ """Click element identified by ``locator``.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
self.info("Clicking element '%s'." % locator)
self.find_element(locator).click()
@keyword
def click_element_at_coordinates(self, locator, xoffset, yoffset):
- """Click element identified by `locator` at x/y coordinates of the element.
+ """Click element ``locator`` at ``xoffset/yoffset``.
+
Cursor is moved and the center of the element and x/y coordinates are
- calculted from that point.
+ calculated from that point.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- self.info("Click clicking element '%s' in coordinates "
- "'%s', '%s'." % (locator, xoffset, yoffset))
+ self.info("Clicking element '%s' at coordinates x=%s, y=%s."
+ % (locator, xoffset, yoffset))
element = self.find_element(locator)
action = ActionChains(self.browser)
action.move_to_element(element)
@@ -449,10 +410,10 @@ def click_element_at_coordinates(self, locator, xoffset, yoffset):
@keyword
def double_click_element(self, locator):
- """Double click element identified by `locator`.
+ """Double click element identified by ``locator``.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
self.info("Double clicking element '%s'." % locator)
element = self.find_element(locator)
@@ -461,7 +422,10 @@ def double_click_element(self, locator):
@keyword
def set_focus_to_element(self, locator):
- """Sets focus to element identified by `locator`.
+ """Sets focus to element identified by ``locator``.
+
+ See the `Locating elements` section for details about the locator
+ syntax.
Prior to SeleniumLibrary 3.0 this keyword was named `Focus`.
"""
@@ -474,68 +438,65 @@ def focus(self, locator):
self.set_focus_to_element(locator)
@keyword
- def drag_and_drop(self, source, target):
- """Drags element identified with `source` which is a locator.
-
- Element can be moved on top of another element with `target`
- argument.
+ def drag_and_drop(self, locator, target):
+ """Drags element identified by ``locator`` into ``target`` element.
- `target` is a locator of the element where the dragged object is
- dropped.
+ The ``locator`` argument is the locator of the dragged element
+ and the ``target`` is the locator of the target. See the
+ `Locating elements` section for details about the locator syntax.
- Examples:
- | Drag And Drop | elem1 | elem2 | # Move elem1 over elem2. |
+ Example:
+ | `Drag And Drop` | css:div#element | css:div.target |
"""
- src_elem = self.find_element(source)
- trg_elem = self.find_element(target)
+ element = self.find_element(locator)
+ target = self.find_element(target)
action = ActionChains(self.browser)
- action.drag_and_drop(src_elem, trg_elem).perform()
+ action.drag_and_drop(element, target).perform()
@keyword
- def drag_and_drop_by_offset(self, source, xoffset, yoffset):
- """Drags element identified with `source` which is a locator.
+ def drag_and_drop_by_offset(self, locator, xoffset, yoffset):
+ """Drags element identified with ``locator`` by ``xoffset/yoffset``.
- Element will be moved by xoffset and yoffset, each of which is a
- negative or positive number specify the offset.
+ See the `Locating elements` section for details about the locator
+ syntax.
- Examples:
- | Drag And Drop By Offset | myElem | 50 | -35 | # Move myElem 50px right and 35px down. |
+ Element will be moved by ``xoffset`` and ``yoffset``, each of which
+ is a negative or positive number specifying the offset.
+
+ Example:
+ | `Drag And Drop By Offset` | myElem | 50 | -35 | # Move myElem 50px right and 35px down |
"""
- src_elem = self.find_element(source)
+ element = self.find_element(locator)
action = ActionChains(self.browser)
- action.drag_and_drop_by_offset(src_elem, xoffset, yoffset)
+ action.drag_and_drop_by_offset(element, int(xoffset), int(yoffset))
action.perform()
@keyword
def mouse_down(self, locator):
- """Simulates pressing the left mouse button on the element specified by `locator`.
+ """Simulates pressing the left mouse button on the element ``locator``.
- The element is pressed without releasing the mouse button.
+ See the `Locating elements` section for details about the locator
+ syntax.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ The element is pressed without releasing the mouse button.
See also the more specific keywords `Mouse Down On Image` and
`Mouse Down On Link`.
"""
- self.info("Simulating Mouse Down on element '%s'" % locator)
- element = self.find_element(locator, required=False)
- if element is None:
- raise AssertionError("ERROR: Element %s not found." % (locator))
+ self.info("Simulating Mouse Down on element '%s'." % locator)
+ element = self.find_element(locator)
action = ActionChains(self.browser)
action.click_and_hold(element).perform()
@keyword
def mouse_out(self, locator):
- """Simulates moving mouse away from the element specified by `locator`.
+ """Simulates moving mouse away from the element ``locator``.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- self.info("Simulating Mouse Out on element '%s'" % locator)
- element = self.find_element(locator, required=False)
- if element is None:
- raise AssertionError("ERROR: Element %s not found." % (locator))
+ self.info("Simulating Mouse Out on element '%s'." % locator)
+ element = self.find_element(locator)
size = element.size
offsetx = (size['width'] / 2) + 1
offsety = (size['height'] / 2) + 1
@@ -545,46 +506,43 @@ def mouse_out(self, locator):
@keyword
def mouse_over(self, locator):
- """Simulates hovering mouse over the element specified by `locator`.
+ """Simulates hovering mouse over the element ``locator``.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- self.info("Simulating Mouse Over on element '%s'" % locator)
- element = self.find_element(locator, required=False)
- if element is None:
- raise AssertionError("ERROR: Element %s not found." % (locator))
+ self.info("Simulating Mouse Over on element '%s'." % locator)
+ element = self.find_element(locator)
action = ActionChains(self.browser)
action.move_to_element(element).perform()
@keyword
def mouse_up(self, locator):
- """Simulates releasing the left mouse button on the element specified by `locator`.
+ """Simulates releasing the left mouse button on the element ``locator``.
- Key attributes for arbitrary elements are `id` and `name`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
"""
- self.info("Simulating Mouse Up on element '%s'" % locator)
- element = self.find_element(locator, required=False)
- if element is None:
- raise AssertionError("ERROR: Element %s not found." % (locator))
+ self.info("Simulating Mouse Up on element '%s'." % locator)
+ element = self.find_element(locator)
ActionChains(self.browser).release(element).perform()
@keyword
def open_context_menu(self, locator):
- """Opens context menu on element identified by `locator`."""
+ """Opens context menu on element identified by ``locator``."""
element = self.find_element(locator)
action = ActionChains(self.browser)
action.context_click(element).perform()
@keyword
def simulate_event(self, locator, event):
- """Simulates `event` on element identified by `locator`.
+ """Simulates ``event`` on element identified by ``locator``.
- This keyword is useful if element has OnEvent handler that needs to be
- explicitly invoked.
+ This keyword is useful if element has ``OnEvent`` handler that
+ needs to be explicitly invoked.
- See `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax.
Prior to SeleniumLibrary 3.0 this keyword was named `Simulate`.
"""
@@ -606,16 +564,20 @@ def simulate(self, locator, event):
"""Deprecated. Use `Simulate Event` instead."""
self.simulate_event(locator, event)
-
@keyword
def press_key(self, locator, key):
- """Simulates user pressing key on element identified by `locator`.
- `key` is either a single character, a string, or a numerical ASCII code of the key
- lead by '\\\\'.
+ r"""Simulates user pressing key on element identified by ``locator``.
+
+ See the `Locating elements` section for details about the locator
+ syntax.
+
+ ``key`` is either a single character, a string, or a numerical ASCII
+ code of the key lead by '\\'.
+
Examples:
- | Press Key | text_field | q |
- | Press Key | text_field | abcde |
- | Press Key | login_button | \\\\13 | # ASCII code for enter key |
+ | `Press Key` | text_field | q |
+ | `Press Key` | text_field | abcde |
+ | `Press Key` | login_button | \\13 | # ASCII code for enter key |
"""
if key.startswith('\\') and len(key) > 1:
key = self._map_ascii_key_code_to_key(int(key[1:]))
@@ -624,14 +586,14 @@ def press_key(self, locator, key):
@keyword
def click_link(self, locator):
- """Clicks a link identified by locator.
+ """Clicks a link identified by ``locator``.
- Key attributes for links are `id`, `name`, `href` and link text. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax. Key attributes for links are ``id``, ``name``, ``href`` and
+ link text.
"""
self.info("Clicking link '%s'." % locator)
- link = self.find_element(locator, tag='a')
- link.click()
+ self.find_element(locator, tag='a').click()
@keyword
def get_all_links(self):
@@ -639,54 +601,53 @@ def get_all_links(self):
If a link has no id, an empty string will be in the list instead.
"""
- links = []
- elements = self.find_element("tag=a", tag='a', first_only=False,
- required=False)
- for anchor in elements:
- links.append(anchor.get_attribute('id'))
- return links
+ links = self.find_elements("tag=a", tag='a')
+ return [link.get_attribute('id') for link in links]
@keyword
def mouse_down_on_link(self, locator):
- """Simulates a mouse down event on a link.
+ """Simulates a mouse down event on a link identified by ``locator``.
- Key attributes for links are `id`, `name`, `href` and link text. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax. Key attributes for links are ``id``, ``name``, ``href`` and
+ link text.
"""
- element = self.find_element(locator, tag='link')
+ element = self.find_element(locator, tag='a')
action = ActionChains(self.browser)
action.click_and_hold(element).perform()
@keyword
- def page_should_contain_link(self, locator, message='', loglevel='INFO'):
- """Verifies link identified by `locator` is found from current page.
+ def page_should_contain_link(self, locator, message=None, loglevel='INFO'):
+ """Verifies link identified by ``locator`` is found from current page.
- See `Page Should Contain Element` for explanation about `message` and
- `loglevel` arguments.
+ See the `Locating elements` section for details about the locator
+ syntax. Key attributes for links are ``id``, ``name``, ``href`` and
+ link text.
- Key attributes for links are `id`, `name`, `href` and link text. See
- `introduction` for details about locating elements.
+ See `Page Should Contain Element` for explanation about ``message``
+ and ``loglevel`` arguments.
"""
self.assert_page_contains(locator, 'link', message, loglevel)
@keyword
- def page_should_not_contain_link(self, locator, message='', loglevel='INFO'):
- """Verifies image identified by `locator` is not found from current page.
+ def page_should_not_contain_link(self, locator, message=None, loglevel='INFO'):
+ """Verifies link identified by ``locator`` is not found from current page.
- See `Page Should Contain Element` for explanation about `message` and
- `loglevel` arguments.
+ See the `Locating elements` section for details about the locator
+ syntax. Key attributes for links are ``id``, ``name``, ``href`` and
+ link text.
- Key attributes for images are `id`, `src` and `alt`. See
- `introduction` for details about locating elements.
+ See `Page Should Contain Element` for explanation about ``message``
+ and ``loglevel`` arguments.
"""
self.assert_page_not_contains(locator, 'link', message, loglevel)
@keyword
def click_image(self, locator):
- """Clicks an image found by `locator`.
+ """Clicks an image identified by ``locator``.
- Key attributes for images are `id`, `src` and `alt`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax. Key attributes for images are ``id``, ``src`` and ``alt``.
"""
self.info("Clicking image '%s'." % locator)
element = self.find_element(locator, tag='image', required=False)
@@ -697,108 +658,71 @@ def click_image(self, locator):
@keyword
def mouse_down_on_image(self, locator):
- """Simulates a mouse down event on an image.
+ """Simulates a mouse down event on an image identified by ``locator``.
- Key attributes for images are `id`, `src` and `alt`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax. Key attributes for images are ``id``, ``src`` and ``alt``.
"""
element = self.find_element(locator, tag='image')
action = ActionChains(self.browser)
action.click_and_hold(element).perform()
@keyword
- def page_should_contain_image(self, locator, message='', loglevel='INFO'):
- """Verifies image identified by `locator` is found from current page.
- See `Page Should Contain Element` for explanation about `message` and
- `loglevel` arguments.
+ def page_should_contain_image(self, locator, message=None, loglevel='INFO'):
+ """Verifies image identified by ``locator`` is found from current page.
- Key attributes for images are `id`, `src` and `alt`. See
- `introduction` for details about locating elements.
+ See the `Locating elements` section for details about the locator
+ syntax. Key attributes for images are ``id``, ``src`` and ``alt``.
+
+ See `Page Should Contain Element` for explanation about ``message``
+ and ``loglevel`` arguments.
"""
self.assert_page_contains(locator, 'image', message, loglevel)
@keyword
- def page_should_not_contain_image(self, locator, message='', loglevel='INFO'):
- """Verifies image identified by `locator` is found from current page.
+ def page_should_not_contain_image(self, locator, message=None, loglevel='INFO'):
+ """Verifies image identified by ``locator`` is found from current page.
- See `Page Should Contain Element` for explanation about `message` and
- `loglevel` arguments.
+ See the `Locating elements` section for details about the locator
+ syntax. Key attributes for images are ``id``, ``src`` and ``alt``.
- Key attributes for images are `id`, `src` and `alt`. See
- `introduction` for details about locating elements.
+ See `Page Should Contain Element` for explanation about ``message``
+ and ``loglevel`` arguments.
"""
self.assert_page_not_contains(locator, 'image', message, loglevel)
@keyword
def get_matching_xpath_count(self, xpath, return_str=True):
- """Returns number of elements matching `xpath`
-
- The default return type is `str` but it can changed to `int` by setting
- the ``return_str`` argument to Python False.
+ """Returns number of elements matching ``xpath``.
- One should not use the xpath= prefix for 'xpath'. XPath is assumed.
+ The default return type is string, but it can changed to an integer
+ by setting the ``return_str`` argument to a false value.
- Correct:
- | count = | Get Matching Xpath Count | //div[@id='sales-pop']
- Incorrect:
- | count = | Get Matching Xpath Count | xpath=//div[@id='sales-pop']
+ The ``xpath`` should not contain ``xpath:`` prefix.
- If you wish to assert the number of matching elements, use
- `Xpath Should Match X Times`.
+ Example:
+ | count = | `Get Matching Xpath Count` | //div[@id='sales-pop'] |
"""
- count = len(self.find_element("xpath=" + xpath, first_only=False,
- required=False))
+ count = len(self.find_elements('xpath:' + xpath))
return str(count) if is_truthy(return_str) else count
@keyword
- def xpath_should_match_x_times(self, xpath, expected_xpath_count, message='', loglevel='INFO'):
- """Verifies that the page contains the given number of elements located by the given `xpath`.
-
- One should not use the xpath= prefix for 'xpath'. XPath is assumed.
-
- Correct:
- | Xpath Should Match X Times | //div[@id='sales-pop'] | 1
- Incorrect:
- | Xpath Should Match X Times | xpath=//div[@id='sales-pop'] | 1
-
- See `Page Should Contain Element` for explanation about `message` and
- `loglevel` arguments.
- """
- actual_xpath_count = len(self.find_element(
- "xpath=" + xpath, first_only=False, required=False))
- if int(actual_xpath_count) != int(expected_xpath_count):
- if is_falsy(message):
- message = ("Xpath %s should have matched %s times but "
- "matched %s times"
- % (xpath, expected_xpath_count, actual_xpath_count))
- self.ctx.log_source(loglevel)
- raise AssertionError(message)
- self.info("Current page contains %s elements matching '%s'."
- % (actual_xpath_count, xpath))
+ def xpath_should_match_x_times(self, xpath, x, message=None, loglevel='INFO'):
+ """Deprecated. Use `Locator Should Match X Times` instead."""
+ self.locator_should_match_x_times('xpath:'+xpath, x, message, loglevel)
@keyword
def add_location_strategy(self, strategy_name, strategy_keyword, persist=False):
- """Adds a custom location strategy based on a keyword.
-
- Location strategies are automatically removed after leaving the current
- scope by default. Setting `persist` to Python True will cause the
- location strategy to stay registered throughout the life of the test.
-
- Trying to add a custom location strategy with the same name as one that
- already exists will cause the keyword to fail.
-
- Custom locator keyword example:
- | Custom Locator Strategy |
- | | [Arguments] | ${browser} | ${criteria} | ${tag} | ${constraints} |
- | | ${retVal}= | Execute Javascript | return window.document.getElementById('${criteria}'); |
- | | [Return] | ${retVal} |
+ """Adds a custom location strategy.
- Usage example:
- | Add Location Strategy | custom | Custom Locator Strategy |
- | Page Should Contain Element | custom=my_id |
+ See `Custom locators` for information how to create and use
+ custom strategies. `Remove Location Strategy` can be used to
+ remove a registered strategy.
- See `Remove Location Strategy` for details about removing a custom
- location strategy.
+ Location strategies are automatically removed after leaving the
+ current scope by default. Setting ``persist`` to a true value (see
+ `Boolean arguments`) will cause the location strategy to stay
+ registered throughout the life of the test.
"""
self.element_finder.register(strategy_name, strategy_keyword, persist)
@@ -806,47 +730,11 @@ def add_location_strategy(self, strategy_name, strategy_keyword, persist=False):
def remove_location_strategy(self, strategy_name):
"""Removes a previously added custom location strategy.
- Will fail if a default strategy is specified.
-
- See `Add Location Strategy` for details about adding a custom location strategy.
+ See `Custom locators` for information how to create and use
+ custom strategies.
"""
self.element_finder.unregister(strategy_name)
- def _frame_contains(self, locator, text):
- element = self.find_element(locator)
- self.browser.switch_to.frame(element)
- self.info("Searching for text from frame '%s'." % locator)
- found = self.is_text_present(text)
- self.browser.switch_to.default_content()
- return found
-
- def _get_text(self, locator):
- element = self.find_element(locator)
- if element is not None:
- return element.text
- return None
-
- def _is_enabled(self, locator):
- element = self.find_element(locator)
- if not self.form_element._is_form_element(element):
- raise AssertionError("ERROR: Element %s is not an input." % locator)
- if not element.is_enabled():
- return False
- read_only = element.get_attribute('readonly')
- if read_only == 'readonly' or read_only == 'true':
- return False
- return True
-
- def is_text_present(self, text):
- locator = "xpath=//*[contains(., %s)]" % escape_xpath_value(text)
- return self.find_element(locator, required=False)
-
- def is_visible(self, locator):
- element = self.find_element(locator, required=False)
- if element is not None:
- return element.is_displayed()
- return None
-
def _map_ascii_key_code_to_key(self, key_code):
map = {
0: Keys.NULL,
@@ -880,24 +768,14 @@ def _map_named_key_code_to_special_key(self, key_name):
self.debug(message)
raise ValueError(message)
- def _parse_attribute_locator(self, attribute_locator):
- parts = attribute_locator.rpartition('@')
- if len(parts[0]) == 0:
- raise ValueError("Attribute locator '%s' does not contain an element locator." % (attribute_locator))
- if len(parts[2]) == 0:
- raise ValueError("Attribute locator '%s' does not contain an attribute name." % (attribute_locator))
- return parts[0], parts[2]
-
def _page_contains(self, text):
self.browser.switch_to.default_content()
if self.is_text_present(text):
return True
- subframes = self.find_element("xpath=//frame|//iframe",
- first_only=False,
- required=False)
- self.debug('Current frame has %d subframes' % len(subframes))
+ subframes = self.find_elements("xpath://frame|//iframe")
+ self.debug('Current frame has %d subframes.' % len(subframes))
for frame in subframes:
self.browser.switch_to.frame(frame)
found_text = self.is_text_present(text)
diff --git a/src/SeleniumLibrary/keywords/formelement.py b/src/SeleniumLibrary/keywords/formelement.py
index 8abc40e9c..e84ad2b0f 100644
--- a/src/SeleniumLibrary/keywords/formelement.py
+++ b/src/SeleniumLibrary/keywords/formelement.py
@@ -17,14 +17,12 @@
import os
from SeleniumLibrary.base import LibraryComponent, keyword
-from SeleniumLibrary.utils import is_falsy
+from SeleniumLibrary.errors import ElementNotFound
+from SeleniumLibrary.utils import is_noney
class FormElementKeywords(LibraryComponent):
- def __init__(self, ctx):
- LibraryComponent.__init__(self, ctx)
-
@keyword
def submit_form(self, locator=None):
"""Submits a form identified by `locator`.
@@ -34,8 +32,8 @@ def submit_form(self, locator=None):
details about locating elements.
"""
self.info("Submitting form '%s'." % locator)
- if is_falsy(locator):
- locator = 'xpath=//form'
+ if is_noney(locator):
+ locator = 'tag:form'
element = self.find_element(locator, tag='form')
element.submit()
@@ -50,7 +48,7 @@ def checkbox_should_be_selected(self, locator):
element = self._get_checkbox(locator)
if not element.is_selected():
raise AssertionError("Checkbox '%s' should have been selected "
- "but was not" % locator)
+ "but was not." % locator)
@keyword
def checkbox_should_not_be_selected(self, locator):
@@ -62,11 +60,11 @@ def checkbox_should_not_be_selected(self, locator):
self.info("Verifying checkbox '%s' is not selected." % locator)
element = self._get_checkbox(locator)
if element.is_selected():
- raise AssertionError("Checkbox '%s' should not have been selected"
- % locator)
+ raise AssertionError("Checkbox '%s' should not have been "
+ "selected." % locator)
@keyword
- def page_should_contain_checkbox(self, locator, message='', loglevel='INFO'):
+ def page_should_contain_checkbox(self, locator, message=None, loglevel='INFO'):
"""Verifies checkbox identified by `locator` is found from current page.
See `Page Should Contain Element` for explanation about `message` and
@@ -78,7 +76,7 @@ def page_should_contain_checkbox(self, locator, message='', loglevel='INFO'):
self.assert_page_contains(locator, 'checkbox', message, loglevel)
@keyword
- def page_should_not_contain_checkbox(self, locator, message='', loglevel='INFO'):
+ def page_should_not_contain_checkbox(self, locator, message=None, loglevel='INFO'):
"""Verifies checkbox identified by `locator` is not found from current page.
See `Page Should Contain Element` for explanation about `message` and
@@ -116,7 +114,7 @@ def unselect_checkbox(self, locator):
element.click()
@keyword
- def page_should_contain_radio_button(self, locator, message='', loglevel='INFO'):
+ def page_should_contain_radio_button(self, locator, message=None, loglevel='INFO'):
"""Verifies radio button identified by `locator` is found from current page.
See `Page Should Contain Element` for explanation about `message` and
@@ -128,7 +126,7 @@ def page_should_contain_radio_button(self, locator, message='', loglevel='INFO')
self.assert_page_contains(locator, 'radio button', message, loglevel)
@keyword
- def page_should_not_contain_radio_button(self, locator, message='', loglevel='INFO'):
+ def page_should_not_contain_radio_button(self, locator, message=None, loglevel='INFO'):
"""Verifies radio button identified by `locator` is not found from current page.
See `Page Should Contain Element` for explanation about `message` and
@@ -153,7 +151,7 @@ def radio_button_should_be_set_to(self, group_name, value):
actual_value = self._get_value_from_radio_buttons(elements)
if actual_value is None or actual_value != value:
raise AssertionError("Selection of radio button '%s' should have "
- "been '%s' but was '%s'"
+ "been '%s' but was '%s'."
% (group_name, value, actual_value))
@keyword
@@ -167,8 +165,8 @@ def radio_button_should_not_be_selected(self, group_name):
elements = self._get_radio_buttons(group_name)
actual_value = self._get_value_from_radio_buttons(elements)
if actual_value is not None:
- raise AssertionError("Radio button group '%s' should not have had "
- "selection, but '%s' was selected"
+ raise AssertionError("Radio button group '%s' should not have "
+ "had selection, but '%s' was selected."
% (group_name, actual_value))
@keyword
@@ -204,8 +202,8 @@ def choose_file(self, locator, file_path):
| Choose File | my_upload_field | /home/user/files/trades.csv |
"""
if not os.path.isfile(file_path):
- raise AssertionError("File '%s' does not exist on the local file system"
- % file_path)
+ raise ValueError("File '%s' does not exist on the local file "
+ "system." % file_path)
self.find_element(locator).send_keys(file_path)
@keyword
@@ -216,7 +214,7 @@ def input_password(self, locator, text):
does not log the given password. See `introduction` for details about
locating elements.
"""
- self.info("Typing password into text field '%s'" % locator)
+ self.info("Typing password into text field '%s'." % locator)
self._input_text_into_text_field(locator, text)
@keyword
@@ -225,11 +223,11 @@ def input_text(self, locator, text):
See `introduction` for details about locating elements.
"""
- self.info("Typing text '%s' into text field '%s'" % (text, locator))
+ self.info("Typing text '%s' into text field '%s'." % (text, locator))
self._input_text_into_text_field(locator, text)
@keyword
- def page_should_contain_textfield(self, locator, message='', loglevel='INFO'):
+ def page_should_contain_textfield(self, locator, message=None, loglevel='INFO'):
"""Verifies text field identified by `locator` is found from current page.
See `Page Should Contain Element` for explanation about `message` and
@@ -241,7 +239,7 @@ def page_should_contain_textfield(self, locator, message='', loglevel='INFO'):
self.assert_page_contains(locator, 'text field', message, loglevel)
@keyword
- def page_should_not_contain_textfield(self, locator, message='', loglevel='INFO'):
+ def page_should_not_contain_textfield(self, locator, message=None, loglevel='INFO'):
"""Verifies text field identified by `locator` is not found from current page.
See `Page Should Contain Element` for explanation about `message` and
@@ -253,7 +251,7 @@ def page_should_not_contain_textfield(self, locator, message='', loglevel='INFO'
self.assert_page_not_contains(locator, 'text field', message, loglevel)
@keyword
- def textfield_should_contain(self, locator, expected, message=''):
+ def textfield_should_contain(self, locator, expected, message=None):
"""Verifies text field identified by `locator` contains text `expected`.
`message` can be used to override default error message.
@@ -261,16 +259,16 @@ def textfield_should_contain(self, locator, expected, message=''):
Key attributes for text fields are `id` and `name`. See `introduction`
for details about locating elements.
"""
- actual = self.element_finder.get_value(locator, 'text field')
+ actual = self._get_value(locator, 'text field')
if expected not in actual:
- if is_falsy(message):
+ if is_noney(message):
message = "Text field '%s' should have contained text '%s' "\
- "but it contained '%s'" % (locator, expected, actual)
+ "but it contained '%s'." % (locator, expected, actual)
raise AssertionError(message)
self.info("Text field '%s' contains text '%s'." % (locator, expected))
@keyword
- def textfield_value_should_be(self, locator, expected, message=''):
+ def textfield_value_should_be(self, locator, expected, message=None):
"""Verifies the value in text field identified by `locator` is exactly `expected`.
`message` can be used to override default error message.
@@ -278,20 +276,16 @@ def textfield_value_should_be(self, locator, expected, message=''):
Key attributes for text fields are `id` and `name`. See `introduction`
for details about locating elements.
"""
- element = self.find_element(locator, tag='text field', required=False)
- if not element:
- element = self.find_element(locator, tag='file upload',
- required=False)
- actual = element.get_attribute('value') if element else None
+ actual = self._get_value(locator, 'text field')
if actual != expected:
- if is_falsy(message):
+ if is_noney(message):
message = "Value of text field '%s' should have been '%s' "\
- "but was '%s'" % (locator, expected, actual)
+ "but was '%s'." % (locator, expected, actual)
raise AssertionError(message)
self.info("Content of text field '%s' is '%s'." % (locator, expected))
@keyword
- def textarea_should_contain(self, locator, expected, message=''):
+ def textarea_should_contain(self, locator, expected, message=None):
"""Verifies text area identified by `locator` contains text `expected`.
`message` can be used to override default error message.
@@ -299,19 +293,16 @@ def textarea_should_contain(self, locator, expected, message=''):
Key attributes for text areas are `id` and `name`. See `introduction`
for details about locating elements.
"""
- actual = self.element_finder.get_value(locator, 'text area')
- if actual is not None:
- if expected not in actual:
- if is_falsy(message):
- message = "Text field '%s' should have contained text '%s' "\
- "but it contained '%s'" % (locator, expected, actual)
- raise AssertionError(message)
- else:
- raise ValueError("Element locator '" + locator + "' did not match any elements.")
+ actual = self._get_value(locator, 'text area')
+ if expected not in actual:
+ if is_noney(message):
+ message = "Text area '%s' should have contained text '%s' " \
+ "but it had '%s'." % (locator, expected, actual)
+ raise AssertionError(message)
self.info("Text area '%s' contains text '%s'." % (locator, expected))
@keyword
- def textarea_value_should_be(self, locator, expected, message=''):
+ def textarea_value_should_be(self, locator, expected, message=None):
"""Verifies the value in text area identified by `locator` is exactly `expected`.
`message` can be used to override default error message.
@@ -319,15 +310,12 @@ def textarea_value_should_be(self, locator, expected, message=''):
Key attributes for text areas are `id` and `name`. See `introduction`
for details about locating elements.
"""
- actual = self.element_finder.get_value(locator, 'text area')
- if actual is not None:
- if expected != actual:
- if is_falsy(message):
- message = "Text field '%s' should have contained text '%s' "\
- "but it contained '%s'" % (locator, expected, actual)
- raise AssertionError(message)
- else:
- raise ValueError("Element locator '" + locator + "' did not match any elements.")
+ actual = self._get_value(locator, 'text area')
+ if expected != actual:
+ if is_noney(message):
+ message = "Text area '%s' should have had text '%s' " \
+ "but it had '%s'." % (locator, expected, actual)
+ raise AssertionError(message)
self.info("Content of text area '%s' is '%s'." % (locator, expected))
@keyword
@@ -344,7 +332,7 @@ def click_button(self, locator):
element.click()
@keyword
- def page_should_contain_button(self, locator, message='', loglevel='INFO'):
+ def page_should_contain_button(self, locator, message=None, loglevel='INFO'):
"""Verifies button identified by `locator` is found from current page.
This keyword searches for buttons created with either `input` or `button` tag.
@@ -361,7 +349,7 @@ def page_should_contain_button(self, locator, message='', loglevel='INFO'):
self.assert_page_contains(locator, 'button', message, loglevel)
@keyword
- def page_should_not_contain_button(self, locator, message='', loglevel='INFO'):
+ def page_should_not_contain_button(self, locator, message=None, loglevel='INFO'):
"""Verifies button identified by `locator` is not found from current page.
This keyword searches for buttons created with either `input` or `button` tag.
@@ -375,19 +363,30 @@ def page_should_not_contain_button(self, locator, message='', loglevel='INFO'):
self.assert_page_not_contains(locator, 'button', message, loglevel)
self.assert_page_not_contains(locator, 'input', message, loglevel)
+ def _get_value(self, locator, tag):
+ return self.find_element(locator, tag).get_attribute('value')
+
def _get_checkbox(self, locator):
return self.find_element(locator, tag='input')
def _get_radio_buttons(self, group_name):
- xpath = "xpath=//input[@type='radio' and @name='%s']" % group_name
+ xpath = "xpath://input[@type='radio' and @name='%s']" % group_name
self.debug('Radio group locator: ' + xpath)
- return self.find_element(xpath, first_only=False)
+ elements = self.find_elements(xpath)
+ if not elements:
+ raise ElementNotFound("No radio button with name '%s' found."
+ % group_name)
+ return elements
def _get_radio_button_with_value(self, group_name, value):
- xpath = "xpath=//input[@type='radio' and @name='%s' and (@value='%s' or @id='%s')]" \
- % (group_name, value, value)
+ xpath = "xpath://input[@type='radio' and @name='%s' and " \
+ "(@value='%s' or @id='%s')]" % (group_name, value, value)
self.debug('Radio group locator: ' + xpath)
- return self.find_element(xpath)
+ try:
+ return self.find_element(xpath)
+ except ElementNotFound:
+ raise ElementNotFound("No radio button with name '%s' and "
+ "value '%s' found." % (group_name, value))
def _get_value_from_radio_buttons(self, elements):
for element in elements:
@@ -399,9 +398,3 @@ def _input_text_into_text_field(self, locator, text):
element = self.find_element(locator)
element.clear()
element.send_keys(text)
-
- def _is_form_element(self, element):
- if element is None:
- return False
- tag = element.tag_name.lower()
- return tag == 'input' or tag == 'select' or tag == 'textarea' or tag == 'button' or tag == 'option'
diff --git a/src/SeleniumLibrary/keywords/frames.py b/src/SeleniumLibrary/keywords/frames.py
new file mode 100644
index 000000000..0587e5401
--- /dev/null
+++ b/src/SeleniumLibrary/keywords/frames.py
@@ -0,0 +1,108 @@
+# Copyright 2008-2011 Nokia Networks
+# Copyright 2011-2016 Ryan Tomac, Ed Manlove and contributors
+# Copyright 2016- Robot Framework Foundation
+#
+# 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.
+
+from SeleniumLibrary.base import LibraryComponent, keyword
+
+
+class FrameKeywords(LibraryComponent):
+
+ @keyword
+ def select_frame(self, locator):
+ """Sets frame identified by ``locator`` as the current frame.
+
+ Key attributes for frames are `id` and `name.` See `introduction` for
+ details about locating elements.
+
+ See `Unselect Frame` to cancel the frame selection and return to the Main frame.
+
+ Please note that the frame search always start from the document root or main frame.
+
+ Example:
+ | Select Frame | xpath: //frame[@name='top]/iframe[@name='left'] | # Selects the 'left' iframe |
+ | Click Link | foo | # Clicks link 'foo' in 'left' iframe |
+ | Unselect Frame | | # Returns to main frame |
+ | Select Frame | left | # Selects the 'top' frame |
+ """
+ self.info("Selecting frame '%s'." % locator)
+ element = self.find_element(locator)
+ self.browser.switch_to.frame(element)
+
+ @keyword
+ def unselect_frame(self):
+ """Sets the top frame as the current frame.
+
+ In practice cancels a previous `Select Frame` call.
+ """
+ self.browser.switch_to.default_content()
+
+ @keyword
+ def current_frame_should_contain(self, text, loglevel='INFO'):
+ """Verifies that current frame contains ``text``.
+
+ See `Page Should Contain` for explanation about the ``loglevel``
+ argument.
+
+ Prior to SeleniumLibrary 3.0 this keyword was named
+ `Current Frame Contains`.
+ """
+ if not self.is_text_present(text):
+ self.log_source(loglevel)
+ raise AssertionError("Frame should have contained text '%s' "
+ "but did not." % text)
+ self.info("Current frame contains text '%s'." % text)
+
+ @keyword
+ def current_frame_contains(self, text, loglevel='INFO'):
+ """Deprecated. Use `Current Frame Should Contain` instead."""
+ self.current_frame_should_contain(text, loglevel)
+
+ @keyword
+ def current_frame_should_not_contain(self, text, loglevel='INFO'):
+ """Verifies that current frame does not contains ``text``.
+
+ See `Page Should Contain` for explanation about the ``loglevel``
+ argument.
+ """
+ if self.is_text_present(text):
+ self.log_source(loglevel)
+ raise AssertionError("Frame should not have contained text '%s' "
+ "but it did." % text)
+ self.info("Current frame did not contain text '%s'." % text)
+
+ @keyword
+ def frame_should_contain(self, locator, text, loglevel='INFO'):
+ """Verifies that frame identified by ``locator`` contains ``text``.
+
+ See the `Locating elements` section for details about the locator
+ syntax.
+
+ See `Page Should Contain` for explanation about the ``loglevel``
+ argument.
+ """
+ if not self._frame_contains(locator, text):
+ self.log_source(loglevel)
+ raise AssertionError("Frame '%s' should have contained text '%s' "
+ "but did not." % (locator, text))
+ self.info("Frame '%s' contains text '%s'." % (locator, text))
+
+ def _frame_contains(self, locator, text):
+ element = self.find_element(locator)
+ self.browser.switch_to.frame(element)
+ self.info("Searching for text from frame '%s'." % locator)
+ found = self.is_text_present(text)
+ self.browser.switch_to.default_content()
+ return found
+
diff --git a/src/SeleniumLibrary/keywords/selectelement.py b/src/SeleniumLibrary/keywords/selectelement.py
index 18c8df726..994a9e7bf 100644
--- a/src/SeleniumLibrary/keywords/selectelement.py
+++ b/src/SeleniumLibrary/keywords/selectelement.py
@@ -23,9 +23,6 @@
class SelectElementKeywords(LibraryComponent):
- def __init__(self, ctx):
- LibraryComponent.__init__(self, ctx)
-
@keyword
def get_list_items(self, locator, value=False):
"""Returns the labels or values in the select list identified by `locator`.
@@ -68,8 +65,9 @@ def get_selected_list_labels(self, locator):
locating elements.
"""
select, options = self._get_select_list_options_selected(locator)
- if len(options) == 0:
- raise ValueError("Select list with locator '%s' does not have any selected values")
+ if not options:
+ raise ValueError("List '%s' does not have any selected values."
+ % locator)
return self._get_labels_for_options(options)
@keyword
@@ -96,7 +94,8 @@ def get_selected_list_values(self, locator):
locating elements.
"""
select, options = self._get_select_list_options_selected(locator)
- if len(options) == 0:
+ # TODO: Should return an empty list, not fail
+ if not options:
raise ValueError("Select list with locator '%s' does not have any selected values")
return self._get_values_for_options(options)
@@ -145,7 +144,7 @@ def list_should_have_no_selections(self, locator):
"(selection was [ %s ])" % (locator, items_str))
@keyword
- def page_should_contain_list(self, locator, message='', loglevel='INFO'):
+ def page_should_contain_list(self, locator, message=None, loglevel='INFO'):
"""Verifies select list identified by `locator` is found from current page.
See `Page Should Contain Element` for explanation about `message` and
@@ -157,7 +156,7 @@ def page_should_contain_list(self, locator, message='', loglevel='INFO'):
self.assert_page_contains(locator, 'list', message, loglevel)
@keyword
- def page_should_not_contain_list(self, locator, message='', loglevel='INFO'):
+ def page_should_not_contain_list(self, locator, message=None, loglevel='INFO'):
"""Verifies select list identified by `locator` is not found from current page.
See `Page Should Contain Element` for explanation about `message` and
diff --git a/src/SeleniumLibrary/keywords/waiting.py b/src/SeleniumLibrary/keywords/waiting.py
index 4bf9b631c..cd1fb1caa 100644
--- a/src/SeleniumLibrary/keywords/waiting.py
+++ b/src/SeleniumLibrary/keywords/waiting.py
@@ -17,17 +17,12 @@
import time
from SeleniumLibrary.base import LibraryComponent, keyword
-from SeleniumLibrary.keywords.element import ElementKeywords
-from SeleniumLibrary.utils import (is_truthy, is_falsy,
- secs_to_timestr, timestr_to_secs)
+from SeleniumLibrary.errors import ElementNotFound
+from SeleniumLibrary.utils import is_noney, secs_to_timestr
class WaitingKeywords(LibraryComponent):
- def __init__(self, ctx):
- LibraryComponent.__init__(self, ctx)
- self.element = ElementKeywords(ctx)
-
@keyword
def wait_for_condition(self, condition, timeout=None, error=None):
"""Waits until the given ``condition`` is true or ``timeout`` expires.
@@ -48,11 +43,11 @@ def wait_for_condition(self, condition, timeout=None, error=None):
if 'return' not in condition:
raise ValueError("Condition '%s' did not have mandatory 'return'."
% condition)
- if is_falsy(error):
- error = "Condition '%s' did not become true in
This is the haystack and somewhere on this page is a needle.
+This is the haystack and somewhere on this page is a needle.
This is more text
This text is inside an identified element