web-dev-qa-db-fra.com

Comment le pilote Web Selenium peut-il connaître l’ouverture de la nouvelle fenêtre, puis reprendre son exécution

L'automatisation d'une application Web à l'aide du pilote Web Selenium pose un problème.

La page Web a un bouton qui, une fois cliqué, ouvre une nouvelle fenêtre. Quand j'utilise le code suivant, il jette OpenQA.Selenium.NoSuchWindowException: No window found 

WebDriver.FindElement(By.Id("id of the button that opens new window")).Click();
//Switch to new window
_WebDriver.SwitchTo().Window("new window name");
//Click on button present on the newly opened window
_WebDriver.FindElement(By.Id("id of button present on newly opened window")).Click();

Pour résoudre le problème ci-dessus, j’ajoute Thread.Sleep(50000); entre le clic de bouton et les instructions SwitchTo.

WebDriver.FindElement(By.Id("id of the button that opens new window")).Click();
Thread.Sleep(50000); //wait
//Switch to new window
_WebDriver.SwitchTo().Window("new window name");
//Click on button present on the newly opened window
_WebDriver.FindElement(By.Id("id of button present on newly opened window")).Click();

Le problème a été résolu, mais je ne souhaite pas utiliser l'instruction Thread.Sleep(50000); car si l'ouverture de la fenêtre prend plus de temps, le code peut échouer et si la fenêtre s'ouvre rapidement, le test ralentit inutilement. 

Existe-t-il un moyen de savoir quand la fenêtre s’est ouverte et que le test peut alors reprendre son exécution?

23
Ozone

Vous pouvez attendre que l'opération réussisse, par exemple en Python:

from Selenium.common.exceptions    import NoSuchWindowException
from Selenium.webdriver.support.ui import WebDriverWait

def found_window(name):
    def predicate(driver):
        try: driver.switch_to_window(name)
        except NoSuchWindowException:
             return False
        else:
             return True # found window
    return predicate

driver.find_element_by_id("id of the button that opens new window").click()        
WebDriverWait(driver, timeout=50).until(found_window("new window name"))
WebDriverWait(driver, timeout=10).until( # wait until the button is available
    lambda x: x.find_element_by_id("id of button present on newly opened window"))\
    .click()
10
jfs

J'utilise ceci pour attendre que la fenêtre soit ouverte et cela fonctionne pour moi.

Code C #:

public static void WaitUntilNewWindowIsOpened(this RemoteWebDriver driver, int expectedNumberOfWindows, int maxRetryCount = 100)
    {
        int returnValue;
        bool boolReturnValue;
        for (var i = 0; i < maxRetryCount; Thread.Sleep(100), i++)
        {
            returnValue = driver.WindowHandles.Count;
            boolReturnValue = (returnValue == expectedNumberOfWindows ? true : false);
            if (boolReturnValue)
            {
                return;
            }
        }
        //try one last time to check for window
        returnValue = driver.WindowHandles.Count;
        boolReturnValue = (returnValue == expectedNumberOfWindows ? true : false);
        if (!boolReturnValue)
        {
            throw new ApplicationException("New window did not open.");
        }
    }

Et puis j'appelle cette méthode dans le code

Extensions.WaitUntilNewWindowIsOpened(driver, 2);
1
DadoH

J'ai finalement trouvé la réponse. J'ai utilisé la méthode ci-dessous pour passer à la nouvelle fenêtre

public String switchwindow(String object, String data){
        try {

        String winHandleBefore = driver.getWindowHandle();

        for(String winHandle : driver.getWindowHandles()){
            driver.switchTo().window(winHandle);
        }
        }catch(Exception e){
        return Constants.KEYWORD_FAIL+ "Unable to Switch Window" + e.getMessage();
        }
        return Constants.KEYWORD_PASS;
        }

Pour passer à la fenêtre parent, j'ai utilisé le code suivant,

 public String switchwindowback(String object, String data){
            try {
                String winHandleBefore = driver.getWindowHandle();
                driver.close(); 
                //Switch back to original browser (first window)
                driver.switchTo().window(winHandleBefore);
                //continue with original browser (first window)
            }catch(Exception e){
            return Constants.KEYWORD_FAIL+ "Unable to Switch to main window" + e.getMessage();
            }
            return Constants.KEYWORD_PASS;
            }

Je pense que cela vous aidera à basculer entre les fenêtres.

1
Prasanna

Bien que cette question ait déjà des réponses, aucune d'entre elles ne m'a été vraiment utile, car je ne pouvais pas me fier à une nouvelle fenêtre. J'avais besoin d'en filtrer encore plus. J'ai donc commencé à utiliser la solution de Dadoh, mais je l'ai peaufinée jusqu'à ce que je trouve cette solution. , espérons que cela sera utile à quelqu'un.

public async Task<string> WaitUntilNewWindowIsOpen(string expectedWindowTitle, bool switchToWindow, int maxRetryCount = 100)
{
    string newWindowHandle = await Task.Run(() =>
    {
        string previousWindowHandle = _driver.CurrentWindowHandle;
        int retries = 0;
        while (retries < maxRetryCount)
        {
            foreach (string handle in _driver.WindowHandles)
            {
                _driver.SwitchTo().Window(handle);
                string title = _driver.Title;
                if (title.Equals(expectedWindowTitle))
                {
                    if(!switchToWindow)
                        _driver.SwitchTo().Window(previousWindowHandle);
                    return handle;
                }
            }
            retries++;
            Thread.Sleep(100);
        }
        return string.Empty;
    });
    return newWindowHandle;
}

Ainsi, dans cette solution, j'ai choisi de passer le titre de la fenêtre attendu comme argument pour que la fonction boucle toutes les fenêtres et compare le nouveau titre de la fenêtre. Ainsi, il est garanti que la fenêtre correcte sera renvoyée. Voici un exemple d'appel à cette méthode:

await WaitUntilNewWindowIsOpen("newWindowTitle", true);
0
HeD_pE