'Python. Selenium. How to wait for new window opens?

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


Solution 1:[1]

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()

Solution 2:[2]

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.

Solution 3:[3]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Louis
Solution 2 Surya
Solution 3 Aruix