-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy pathconditions.py
125 lines (104 loc) · 4.49 KB
/
conditions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
"""
Provides additional expected conditions as well as *negatable* versions of selenium's expected conditions.
"""
from selenium.common.exceptions import NoSuchElementException, StaleElementReferenceException
from selenium.webdriver.support import expected_conditions as EC
class NegationMixin(object):
"""
Provides the ability to test the negation of any existing expected condition (EC).
Currently, there is an unsolved problem in certain ECs due to the way exceptions are caught.
"""
def __init__(self, *args, **kwargs):
negative = kwargs.pop('negative', False)
super(NegationMixin, self).__init__(*args, **kwargs)
self.negative = negative
def __call__(self, *args, **kwargs):
try:
result = super(NegationMixin, self).__call__(*args, **kwargs)
except StaleElementReferenceException:
return False # Stale elements are unreliable, always try to regrab the element
if self.negative:
return not result
return result
class AnyTextMixin(object):
"""
Provides default for text_ arguments when the EC expects it. An empty value will test true when
tested against any other string. For example, with selenium's ``text_to_be_present_in_element`` that checks
>>> if element_text:
... return self.text in element_text
In effect, to the desired behavior of accepting just any text because ``'' in any_string`` is always ``True``
>>> if element_text:
... return True
This behavior only applies if the text_ keyword argument is not provided.
This may cause problems if you try to provide text_ as a positional argument, so don't do that.
"""
def __init__(self, *args, **kwargs):
if 'text_' not in kwargs:
kwargs['text_'] = ''
super(AnyTextMixin, self).__init__(*args, **kwargs)
class element_is_selected(NegationMixin, EC.element_located_to_be_selected):
"""
Like selenium's element_located_to_be_selected but with the :ref:`~behave_webdriver.conditions.NegationMixin`.
"""
pass
class element_is_visible(NegationMixin, EC.visibility_of_element_located):
"""
Like selenium's visibility_of_element_located but with the :ref:`~behave_webdriver.conditions.NegationMixin`.
"""
pass
class element_is_present(NegationMixin, EC.presence_of_element_located):
"""
Like selenium's presence_of_element_located but with the :ref:`~behave_webdriver.conditions.NegationMixin`.
"""
def __call__(self, driver):
"""
extends __call__ to catch NoSuchElementException errors to support negation of element existing.
"""
try:
return super(element_is_present, self).__call__(driver)
except NoSuchElementException:
result = False
if self.negative:
return not result
return result
class element_is_enabled(object):
"""
A new EC that checks a webelement's ``is_enabled`` method.
Negation is supplied manually, rather than the usual mixin.
"""
def __init__(self, locator, negative=False):
self.locator = locator
self.negative = negative
def __call__(self, driver):
try:
element = driver.find_element(*self.locator)
except StaleElementReferenceException:
return False
result = element.is_enabled()
if self.negative:
return not result
return result
class element_contains_text(NegationMixin, AnyTextMixin, EC.text_to_be_present_in_element):
"""
Like selenium's text_to_be_present_in_element but with the :ref:`~behave_webdriver.conditions.NegationMixin`.
and :ref:`~behave_webdriver.conditions.AnyTextMixin`.
"""
def __call__(self, driver):
"""
Same logic as in EC.text_to_be_present_in_element except StaleElementReferenceException is not caught
this, for now, is needed to distinguish if a False return value is the result of this exception.
"""
try:
element = driver.find_element(*self.locator)
result = bool(element.text)
except StaleElementReferenceException:
return False
if self.negative:
return not result
return result
class element_contains_value(NegationMixin, AnyTextMixin, EC.text_to_be_present_in_element_value):
"""
Like selenium's text_to_be_present_in_element_value but with the :ref:`~behave_webdriver.conditions.NegationMixin`.
and :ref:`~behave_webdriver.conditions.AnyTextMixin`.
"""
pass