Python. Selenium. How to wait for new window opens?
Asked Answered
E

3

6

I have a button with twitter, and after click new window opens, but before opening there is a timout in few seconds, so is there a way to wait for it? I mait in a bad way for now...

    Ui.click_el(link.W9FormNodes.TWITTER_BUTTON)
    # Wait for new window and switch to it
    time.sleep(3)
    aw = driver.window_handles
    driver.switch_to_window(aw[1])

So I need something better, that will wait only that amount of seconds that needs.

I think I solve it in this way. But maybe someone will have comments how to do it better.

    aw = Ui.click_and_wait_for_window(link.W9FormNodes.TWITTER_BUTTON)
    driver.switch_to_window(aw[1])

And here is a method that click on button and wait for new window:

    def click_and_wait_for_window(self, node):
        current_value = old_value = self.driver.window_handles
        self.click_el(node)
        while len(current_value) == len(old_value):
            time.sleep(0.05)
            current_value = self.driver.window_handles
        return current_value
Employment answered 29/10, 2014 at 22:30 Comment(0)
A
9

As Surya mentioned, WebDriverWait would be the way to wait for a change. You could have a context manager like this that only implements the wait logic and then use it for any kind of operation you care about:

@contextmanager
def wait_for_new_window(driver, timeout=10):
    handles_before = driver.window_handles
    yield
    WebDriverWait(driver, timeout).until(
        lambda driver: len(handles_before) != len(driver.window_handles))

Here's a full working example:

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

from contextlib import contextmanager

@contextmanager
def wait_for_new_window(driver, timeout=10):
    handles_before = driver.window_handles
    yield
    WebDriverWait(driver, timeout).until(
        lambda driver: len(handles_before) != len(driver.window_handles))

driver = webdriver.Chrome()

driver.get("http://www.google.com")

with wait_for_new_window(driver):
    driver.execute_script("""
    window.open("http://www.google.com", "_blank");
    """)

with wait_for_new_window(driver, 2):
    pass # This will obviously hit the timeout.

driver.quit()
Auriga answered 30/10, 2014 at 8:41 Comment(3)
Thanks for answer. Just to clarify. lambda driver: is waiting until condition in it will satisfied? And also can you tell me what is "yield" and "with"?Employment
Yes. If if the lambda evaluates to a true value, this means the condition is satisfied and the wait ends. If it evaluates to a false value, then the wait continues (as long as the timeout limit is not met).Auriga
Already implement this wait. Works really great! Thank you! A bit complex for me with "with" and "yield" so I just take that condition for lambda driver:. Thank you again!Employment
T
1

Now there has a function in the selenium.webdriver.support.expected_conditions package. For example:

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
WebDriverWait(web, 20).until(EC.new_window_is_opened(driver.window_handles))

It will wait for the new window opens.

Tsarevna answered 23/4, 2022 at 17:4 Comment(0)
S
0

Yes; your implementation looks fine. Only thing is you need to set the timeout, otherwise it will wait for ever, if new window doesn't open.

You can combine with WebDriverWait(driver, 10).until.. to set the timeout. Hope this helps.

Schulze answered 30/10, 2014 at 5:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.