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