Skip to content

Commit 6f73d79

Browse files
committed
Add custom expectation to wait for n elements
1 parent dea186d commit 6f73d79

File tree

2 files changed

+55
-6
lines changed

2 files changed

+55
-6
lines changed

notebook/tests/selenium/test_display_isolation.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def isolated_html(notebook):
4242
isolated)
4343
notebook.add_and_execute_cell(content=display_i)
4444

45-
wait_for_tag(notebook.browser, "iframe")
45+
iframe = wait_for_tag(notebook.browser, "iframe", single=True)
4646

4747
# The non-isolated div will be in the body
4848
non_isolated_div = notebook.body.find_element_by_id("non-isolated")
@@ -53,7 +53,6 @@ def isolated_html(notebook):
5353
assert test_div.value_of_css_property("color") == red
5454

5555
# The isolated div will be in an iframe, only that element will be blue
56-
iframe = notebook.body.find_element_by_tag_name("iframe")
5756
notebook.browser.switch_to.frame(iframe)
5857
isolated_div = notebook.browser.find_element_by_id("isolated")
5958
assert isolated_div.value_of_css_property("color") == blue
@@ -79,8 +78,7 @@ def isolated_svg(notebook):
7978
content="display_svg(SVG(s1), metadata=dict(isolated=True))")
8079
notebook.add_and_execute_cell(
8180
content="display_svg(SVG(s2), metadata=dict(isolated=True))")
82-
wait_for_tag(notebook.browser, "iframe")
83-
iframes = notebook.body.find_elements_by_tag_name("iframe")
81+
iframes = wait_for_tag(notebook.browser, "iframe", wait_for_n=2)
8482

8583
# The first rectangle will be red
8684
notebook.browser.switch_to.frame(iframes[0])

notebook/tests/selenium/utils.py

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import time
33
from selenium.webdriver import ActionChains
44
from selenium.webdriver.common.by import By
5+
from selenium.common.exceptions import WebDriverException
56
from selenium.webdriver.common.keys import Keys
67
from selenium.webdriver.support.ui import WebDriverWait
78
from selenium.webdriver.support import expected_conditions as EC
@@ -12,13 +13,33 @@
1213
pjoin = os.path.join
1314

1415

15-
def wait_for_selector(driver, selector, timeout=10, visible=False, single=False):
16+
def wait_for_selector(driver, selector, timeout=10, visible=False, single=False, wait_for_n=1):
17+
if wait_for_n > 1:
18+
return _wait_for_multiple(
19+
driver, By.CSS_SELECTOR, selector, timeout, wait_for_n, visible)
1620
return _wait_for(driver, By.CSS_SELECTOR, selector, timeout, visible, single)
1721

18-
def wait_for_tag(driver, tag, timeout=10, visible=False, single=False):
22+
23+
def wait_for_tag(driver, tag, timeout=10, visible=False, single=False, wait_for_n=1):
24+
if wait_for_n > 1:
25+
return _wait_for_multiple(
26+
driver, By.TAG_NAME, tag, timeout, wait_for_n, visible)
1927
return _wait_for(driver, By.TAG_NAME, tag, timeout, visible, single)
2028

29+
2130
def _wait_for(driver, locator_type, locator, timeout=10, visible=False, single=False):
31+
"""Waits `timeout` seconds for the specified condition to be met. Condition is
32+
met if any matching element is found. Returns located element(s) when found.
33+
34+
Args:
35+
driver: Selenium web driver instance
36+
locator_type: type of locator (e.g. By.CSS_SELECTOR or By.TAG_NAME)
37+
locator: name of tag, class, etc. to wait for
38+
timeout: how long to wait for presence/visibility of element
39+
visible: if True, require that element is not only present, but visible
40+
single: if True, return a single element, otherwise return a list of matching
41+
elements
42+
"""
2243
wait = WebDriverWait(driver, timeout)
2344
if single:
2445
if visible:
@@ -33,6 +54,36 @@ def _wait_for(driver, locator_type, locator, timeout=10, visible=False, single=F
3354
return wait.until(conditional((locator_type, locator)))
3455

3556

57+
def _wait_for_multiple(driver, locator_type, locator, timeout, wait_for_n, visible=False):
58+
"""Waits until `wait_for_n` matching elements to be present (or visible).
59+
Returns located elements when found.
60+
61+
Args:
62+
driver: Selenium web driver instance
63+
locator_type: type of locator (e.g. By.CSS_SELECTOR or By.TAG_NAME)
64+
locator: name of tag, class, etc. to wait for
65+
timeout: how long to wait for presence/visibility of element
66+
wait_for_n: wait until this number of matching elements are present/visible
67+
visible: if True, require that elements are not only present, but visible
68+
"""
69+
wait = WebDriverWait(driver, timeout)
70+
71+
def multiple_found(driver):
72+
try:
73+
elements = driver.find_elements(locator_type, locator)
74+
except WebDriverException as e:
75+
raise e
76+
if len(elements) < wait_for_n:
77+
return False
78+
if visible:
79+
for element in elements:
80+
if not element.is_displayed():
81+
return False
82+
return elements
83+
84+
return wait.until(multiple_found)
85+
86+
3687
class CellTypeError(ValueError):
3788

3889
def __init__(self, message=""):

0 commit comments

Comments
 (0)