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?
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()
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);
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.
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);