tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

expected.py (9385B)


      1 # This Source Code Form is subject to the terms of the Mozilla Public
      2 # License, v. 2.0. If a copy of the MPL was not distributed with this
      3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 
      5 import types
      6 
      7 from . import errors
      8 from .marionette import WebElement
      9 
     10 """This file provides a set of expected conditions for common use
     11 cases when writing Marionette tests.
     12 
     13 The conditions rely on explicit waits that retries conditions a number
     14 of times until they are either successfully met, or they time out.
     15 
     16 """
     17 
     18 
     19 class element_present:
     20    """Checks that a web element is present in the DOM of the current
     21    context.  This does not necessarily mean that the element is
     22    visible.
     23 
     24    You can select which element to be checked for presence by
     25    supplying a locator::
     26 
     27        el = Wait(marionette).until(expected.element_present(By.ID, "foo"))
     28 
     29    Or by using a function/lambda returning an element::
     30 
     31        el = Wait(marionette).until(
     32            expected.element_present(lambda m: m.find_element(By.ID, "foo")))
     33 
     34    :param args: locator or function returning web element
     35    :returns: the web element once it is located, or False
     36 
     37    """
     38 
     39    def __init__(self, *args):
     40        if len(args) == 1 and isinstance(args[0], types.FunctionType):
     41            self.locator = args[0]
     42        else:
     43            self.locator = lambda m: m.find_element(*args)
     44 
     45    def __call__(self, marionette):
     46        return _find(marionette, self.locator)
     47 
     48 
     49 class element_not_present(element_present):
     50    """Checks that a web element is not present in the DOM of the current
     51    context.
     52 
     53    You can select which element to be checked for lack of presence by
     54    supplying a locator::
     55 
     56        r = Wait(marionette).until(expected.element_not_present(By.ID, "foo"))
     57 
     58    Or by using a function/lambda returning an element::
     59 
     60        r = Wait(marionette).until(
     61            expected.element_present(lambda m: m.find_element(By.ID, "foo")))
     62 
     63    :param args: locator or function returning web element
     64    :returns: True if element is not present, or False if it is present
     65 
     66    """
     67 
     68    def __init__(self, *args):
     69        super().__init__(*args)
     70 
     71    def __call__(self, marionette):
     72        return not super().__call__(marionette)
     73 
     74 
     75 class element_stale:
     76    """Check that the given element is no longer attached to DOM of the
     77    current context.
     78 
     79    This can be useful for waiting until an element is no longer
     80    present.
     81 
     82    Sample usage::
     83 
     84        el = marionette.find_element(By.ID, "foo")
     85        # ...
     86        Wait(marionette).until(expected.element_stale(el))
     87 
     88    :param element: the element to wait for
     89    :returns: False if the element is still attached to the DOM, True
     90        otherwise
     91 
     92    """
     93 
     94    def __init__(self, element):
     95        self.el = element
     96 
     97    def __call__(self, marionette):
     98        try:
     99            # Calling any method forces a staleness check
    100            self.el.is_enabled()
    101            return False
    102        except (errors.StaleElementException, errors.NoSuchElementException):
    103            # StaleElementException is raised when the element is gone, and
    104            # NoSuchElementException is raised after a process swap.
    105            return True
    106 
    107 
    108 class elements_present:
    109    """Checks that web elements are present in the DOM of the current
    110    context.  This does not necessarily mean that the elements are
    111    visible.
    112 
    113    You can select which elements to be checked for presence by
    114    supplying a locator::
    115 
    116        els = Wait(marionette).until(expected.elements_present(By.TAG_NAME, "a"))
    117 
    118    Or by using a function/lambda returning a list of elements::
    119 
    120        els = Wait(marionette).until(
    121            expected.elements_present(lambda m: m.find_elements(By.TAG_NAME, "a")))
    122 
    123    :param args: locator or function returning a list of web elements
    124    :returns: list of web elements once they are located, or False
    125 
    126    """
    127 
    128    def __init__(self, *args):
    129        if len(args) == 1 and isinstance(args[0], types.FunctionType):
    130            self.locator = args[0]
    131        else:
    132            self.locator = lambda m: m.find_elements(*args)
    133 
    134    def __call__(self, marionette):
    135        return _find(marionette, self.locator)
    136 
    137 
    138 class elements_not_present(elements_present):
    139    """Checks that web elements are not present in the DOM of the
    140    current context.
    141 
    142    You can select which elements to be checked for not being present
    143    by supplying a locator::
    144 
    145        r = Wait(marionette).until(expected.elements_not_present(By.TAG_NAME, "a"))
    146 
    147    Or by using a function/lambda returning a list of elements::
    148 
    149        r = Wait(marionette).until(
    150            expected.elements_not_present(lambda m: m.find_elements(By.TAG_NAME, "a")))
    151 
    152    :param args: locator or function returning a list of web elements
    153    :returns: True if elements are missing, False if one or more are
    154        present
    155 
    156    """
    157 
    158    def __init__(self, *args):
    159        super().__init__(*args)
    160 
    161    def __call__(self, marionette):
    162        return not super().__call__(marionette)
    163 
    164 
    165 class element_displayed:
    166    """An expectation for checking that an element is visible.
    167 
    168    Visibility means that the element is not only displayed, but also
    169    has a height and width that is greater than 0 pixels.
    170 
    171    Stale elements, meaning elements that have been detached from the
    172    DOM of the current context are treated as not being displayed,
    173    meaning this expectation is not analogous to the behaviour of
    174    calling :func:`~marionette_driver.marionette.WebElement.is_displayed`
    175    on an :class:`~marionette_driver.marionette.WebElement`.
    176 
    177    You can select which element to be checked for visibility by
    178    supplying a locator::
    179 
    180        displayed = Wait(marionette).until(expected.element_displayed(By.ID, "foo"))
    181 
    182    Or by supplying an element::
    183 
    184        el = marionette.find_element(By.ID, "foo")
    185        displayed = Wait(marionette).until(expected.element_displayed(el))
    186 
    187    :param args: locator or web element
    188    :returns: True if element is displayed, False if hidden
    189 
    190    """
    191 
    192    def __init__(self, *args):
    193        self.el = None
    194        if len(args) == 1 and isinstance(args[0], WebElement):
    195            self.el = args[0]
    196        else:
    197            self.locator = lambda m: m.find_element(*args)
    198 
    199    def __call__(self, marionette):
    200        if self.el is None:
    201            self.el = _find(marionette, self.locator)
    202        if not self.el:
    203            return False
    204        try:
    205            return self.el.is_displayed()
    206        except errors.StaleElementException:
    207            return False
    208 
    209 
    210 class element_not_displayed(element_displayed):
    211    """An expectation for checking that an element is not visible.
    212 
    213    Visibility means that the element is not only displayed, but also
    214    has a height and width that is greater than 0 pixels.
    215 
    216    Stale elements, meaning elements that have been detached fom the
    217    DOM of the current context are treated as not being displayed,
    218    meaning this expectation is not analogous to the behaviour of
    219    calling :func:`~marionette_driver.marionette.WebElement.is_displayed`
    220    on an :class:`~marionette_driver.marionette.WebElement`.
    221 
    222    You can select which element to be checked for visibility by
    223    supplying a locator::
    224 
    225        hidden = Wait(marionette).until(expected.element_not_displayed(By.ID, "foo"))
    226 
    227    Or by supplying an element::
    228 
    229        el = marionette.find_element(By.ID, "foo")
    230        hidden = Wait(marionette).until(expected.element_not_displayed(el))
    231 
    232    :param args: locator or web element
    233    :returns: True if element is hidden, False if displayed
    234 
    235    """
    236 
    237    def __init__(self, *args):
    238        super().__init__(*args)
    239 
    240    def __call__(self, marionette):
    241        return not super().__call__(marionette)
    242 
    243 
    244 class element_selected:
    245    """An expectation for checking that the given element is selected.
    246 
    247    :param element: the element to be selected
    248    :returns: True if element is selected, False otherwise
    249 
    250    """
    251 
    252    def __init__(self, element):
    253        self.el = element
    254 
    255    def __call__(self, marionette):
    256        return self.el.is_selected()
    257 
    258 
    259 class element_not_selected(element_selected):
    260    """An expectation for checking that the given element is not
    261    selected.
    262 
    263    :param element: the element to not be selected
    264    :returns: True if element is not selected, False if selected
    265 
    266    """
    267 
    268    def __init__(self, element):
    269        super().__init__(element)
    270 
    271    def __call__(self, marionette):
    272        return not super().__call__(marionette)
    273 
    274 
    275 class element_enabled:
    276    """An expectation for checking that the given element is enabled.
    277 
    278    :param element: the element to check if enabled
    279    :returns: True if element is enabled, False otherwise
    280 
    281    """
    282 
    283    def __init__(self, element):
    284        self.el = element
    285 
    286    def __call__(self, marionette):
    287        return self.el.is_enabled()
    288 
    289 
    290 class element_not_enabled(element_enabled):
    291    """An expectation for checking that the given element is disabled.
    292 
    293    :param element: the element to check if disabled
    294    :returns: True if element is disabled, False if enabled
    295 
    296    """
    297 
    298    def __init__(self, element):
    299        super().__init__(element)
    300 
    301    def __call__(self, marionette):
    302        return not super().__call__(marionette)
    303 
    304 
    305 def _find(marionette, func):
    306    el = None
    307 
    308    try:
    309        el = func(marionette)
    310    except errors.NoSuchElementException:
    311        pass
    312 
    313    if el is None:
    314        return False
    315    return el