expected_conditions.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. # Licensed to the Software Freedom Conservancy (SFC) under one
  2. # or more contributor license agreements. See the NOTICE file
  3. # distributed with this work for additional information
  4. # regarding copyright ownership. The SFC licenses this file
  5. # to you under the Apache License, Version 2.0 (the
  6. # "License"); you may not use this file except in compliance
  7. # with the License. You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing,
  12. # software distributed under the License is distributed on an
  13. # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. # KIND, either express or implied. See the License for the
  15. # specific language governing permissions and limitations
  16. # under the License.
  17. from selenium.common.exceptions import NoSuchElementException
  18. from selenium.common.exceptions import NoSuchFrameException
  19. from selenium.common.exceptions import StaleElementReferenceException
  20. from selenium.common.exceptions import WebDriverException
  21. from selenium.common.exceptions import NoAlertPresentException
  22. """
  23. * Canned "Expected Conditions" which are generally useful within webdriver
  24. * tests.
  25. """
  26. class title_is(object):
  27. """An expectation for checking the title of a page.
  28. title is the expected title, which must be an exact match
  29. returns True if the title matches, false otherwise."""
  30. def __init__(self, title):
  31. self.title = title
  32. def __call__(self, driver):
  33. return self.title == driver.title
  34. class title_contains(object):
  35. """ An expectation for checking that the title contains a case-sensitive
  36. substring. title is the fragment of title expected
  37. returns True when the title matches, False otherwise
  38. """
  39. def __init__(self, title):
  40. self.title = title
  41. def __call__(self, driver):
  42. return self.title in driver.title
  43. class presence_of_element_located(object):
  44. """ An expectation for checking that an element is present on the DOM
  45. of a page. This does not necessarily mean that the element is visible.
  46. locator - used to find the element
  47. returns the WebElement once it is located
  48. """
  49. def __init__(self, locator):
  50. self.locator = locator
  51. def __call__(self, driver):
  52. return _find_element(driver, self.locator)
  53. class visibility_of_element_located(object):
  54. """ An expectation for checking that an element is present on the DOM of a
  55. page and visible. Visibility means that the element is not only displayed
  56. but also has a height and width that is greater than 0.
  57. locator - used to find the element
  58. returns the WebElement once it is located and visible
  59. """
  60. def __init__(self, locator):
  61. self.locator = locator
  62. def __call__(self, driver):
  63. try:
  64. return _element_if_visible(_find_element(driver, self.locator))
  65. except StaleElementReferenceException:
  66. return False
  67. class visibility_of(object):
  68. """ An expectation for checking that an element, known to be present on the
  69. DOM of a page, is visible. Visibility means that the element is not only
  70. displayed but also has a height and width that is greater than 0.
  71. element is the WebElement
  72. returns the (same) WebElement once it is visible
  73. """
  74. def __init__(self, element):
  75. self.element = element
  76. def __call__(self, ignored):
  77. return _element_if_visible(self.element)
  78. def _element_if_visible(element, visibility=True):
  79. return element if element.is_displayed() == visibility else False
  80. class presence_of_all_elements_located(object):
  81. """ An expectation for checking that there is at least one element present
  82. on a web page.
  83. locator is used to find the element
  84. returns the list of WebElements once they are located
  85. """
  86. def __init__(self, locator):
  87. self.locator = locator
  88. def __call__(self, driver):
  89. return _find_elements(driver, self.locator)
  90. class visibility_of_any_elements_located(object):
  91. """ An expectation for checking that there is at least one element visible
  92. on a web page.
  93. locator is used to find the element
  94. returns the list of WebElements once they are located
  95. """
  96. def __init__(self, locator):
  97. self.locator = locator
  98. def __call__(self, driver):
  99. return [element for element in _find_elements(driver, self.locator) if _element_if_visible(element)]
  100. class visibility_of_all_elements_located(object):
  101. """ An expectation for checking that all elements are present on the DOM of a
  102. page and visible. Visibility means that the elements are not only displayed
  103. but also has a height and width that is greater than 0.
  104. locator - used to find the elements
  105. returns the list of WebElements once they are located and visible
  106. """
  107. def __init__(self, locator):
  108. self.locator = locator
  109. def __call__(self, driver):
  110. try:
  111. elements = _find_elements(driver, self.locator)
  112. for element in elements:
  113. if _element_if_visible(element, visibility=False):
  114. return False
  115. return elements
  116. except StaleElementReferenceException:
  117. return False
  118. class text_to_be_present_in_element(object):
  119. """ An expectation for checking if the given text is present in the
  120. specified element.
  121. locator, text
  122. """
  123. def __init__(self, locator, text_):
  124. self.locator = locator
  125. self.text = text_
  126. def __call__(self, driver):
  127. try:
  128. element_text = _find_element(driver, self.locator).text
  129. return self.text in element_text
  130. except StaleElementReferenceException:
  131. return False
  132. class text_to_be_present_in_element_value(object):
  133. """
  134. An expectation for checking if the given text is present in the element's
  135. locator, text
  136. """
  137. def __init__(self, locator, text_):
  138. self.locator = locator
  139. self.text = text_
  140. def __call__(self, driver):
  141. try:
  142. element_text = _find_element(driver,
  143. self.locator).get_attribute("value")
  144. if element_text:
  145. return self.text in element_text
  146. else:
  147. return False
  148. except StaleElementReferenceException:
  149. return False
  150. class frame_to_be_available_and_switch_to_it(object):
  151. """ An expectation for checking whether the given frame is available to
  152. switch to. If the frame is available it switches the given driver to the
  153. specified frame.
  154. """
  155. def __init__(self, locator):
  156. self.frame_locator = locator
  157. def __call__(self, driver):
  158. try:
  159. if isinstance(self.frame_locator, tuple):
  160. driver.switch_to.frame(_find_element(driver,
  161. self.frame_locator))
  162. else:
  163. driver.switch_to.frame(self.frame_locator)
  164. return True
  165. except NoSuchFrameException:
  166. return False
  167. class invisibility_of_element_located(object):
  168. """ An Expectation for checking that an element is either invisible or not
  169. present on the DOM.
  170. locator used to find the element
  171. """
  172. def __init__(self, locator):
  173. self.locator = locator
  174. def __call__(self, driver):
  175. try:
  176. return _element_if_visible(_find_element(driver, self.locator), False)
  177. except (NoSuchElementException, StaleElementReferenceException):
  178. # In the case of NoSuchElement, returns true because the element is
  179. # not present in DOM. The try block checks if the element is present
  180. # but is invisible.
  181. # In the case of StaleElementReference, returns true because stale
  182. # element reference implies that element is no longer visible.
  183. return True
  184. class element_to_be_clickable(object):
  185. """ An Expectation for checking an element is visible and enabled such that
  186. you can click it."""
  187. def __init__(self, locator):
  188. self.locator = locator
  189. def __call__(self, driver):
  190. element = visibility_of_element_located(self.locator)(driver)
  191. if element and element.is_enabled():
  192. return element
  193. else:
  194. return False
  195. class staleness_of(object):
  196. """ Wait until an element is no longer attached to the DOM.
  197. element is the element to wait for.
  198. returns False if the element is still attached to the DOM, true otherwise.
  199. """
  200. def __init__(self, element):
  201. self.element = element
  202. def __call__(self, ignored):
  203. try:
  204. # Calling any method forces a staleness check
  205. self.element.is_enabled()
  206. return False
  207. except StaleElementReferenceException:
  208. return True
  209. class element_to_be_selected(object):
  210. """ An expectation for checking the selection is selected.
  211. element is WebElement object
  212. """
  213. def __init__(self, element):
  214. self.element = element
  215. def __call__(self, ignored):
  216. return self.element.is_selected()
  217. class element_located_to_be_selected(object):
  218. """An expectation for the element to be located is selected.
  219. locator is a tuple of (by, path)"""
  220. def __init__(self, locator):
  221. self.locator = locator
  222. def __call__(self, driver):
  223. return _find_element(driver, self.locator).is_selected()
  224. class element_selection_state_to_be(object):
  225. """ An expectation for checking if the given element is selected.
  226. element is WebElement object
  227. is_selected is a Boolean."
  228. """
  229. def __init__(self, element, is_selected):
  230. self.element = element
  231. self.is_selected = is_selected
  232. def __call__(self, ignored):
  233. return self.element.is_selected() == self.is_selected
  234. class element_located_selection_state_to_be(object):
  235. """ An expectation to locate an element and check if the selection state
  236. specified is in that state.
  237. locator is a tuple of (by, path)
  238. is_selected is a boolean
  239. """
  240. def __init__(self, locator, is_selected):
  241. self.locator = locator
  242. self.is_selected = is_selected
  243. def __call__(self, driver):
  244. try:
  245. element = _find_element(driver, self.locator)
  246. return element.is_selected() == self.is_selected
  247. except StaleElementReferenceException:
  248. return False
  249. class number_of_windows_to_be(object):
  250. """ An expectation for the number of windows to be a certain value."""
  251. def __init__(self, num_windows):
  252. self.num_windows = num_windows
  253. def __call__(self, driver):
  254. return len(driver.window_handles) == self.num_windows
  255. class new_window_is_opened(object):
  256. """ An expectation that a new window will be opened and have the number of
  257. windows handles increase"""
  258. def __init__(self, current_handles):
  259. self.current_handles = current_handles
  260. def __call__(self, driver):
  261. return len(driver.window_handles) > len(self.current_handles)
  262. class alert_is_present(object):
  263. """ Expect an alert to be present."""
  264. def __init__(self):
  265. pass
  266. def __call__(self, driver):
  267. try:
  268. alert = driver.switch_to.alert
  269. alert.text
  270. return alert
  271. except NoAlertPresentException:
  272. return False
  273. def _find_element(driver, by):
  274. """Looks up an element. Logs and re-raises ``WebDriverException``
  275. if thrown."""
  276. try:
  277. return driver.find_element(*by)
  278. except NoSuchElementException as e:
  279. raise e
  280. except WebDriverException as e:
  281. raise e
  282. def _find_elements(driver, by):
  283. try:
  284. return driver.find_elements(*by)
  285. except WebDriverException as e:
  286. raise e