web-dev-qa-db-fra.com

Selenium WebDriver - détermine si l’élément est cliquable (c’est-à-dire qu’il n’est pas masqué par la visionneuse modale du dojo)

J'écris des scripts automatisés pour tester des applications Web très lourdes sur ajax. Par exemple, une boîte de dialogue modale s’affiche avec le texte "Saving..." lors de l’enregistrement des paramètres, tandis que la visionneuse grise le reste de la page.

Mes scripts de test essaient de cliquer sur le lien suivant du test avant que le message ne disparaisse. Cela fonctionne presque toujours avec Firefox, mais l'erreur suivante est affichée lors de l'utilisation de Chrome:

Exception in thread "main" org.openqa.Selenium.WebDriverException: Element is not clickable at point (99.5, 118.5). Other element would receive the click: <div class="dijitDialogUnderlay _underlay" dojoattachpoint="node" id="lfn10Dijit_freedom_widget_common_environment_Dialog_8_underlay" style="width: 1034px; height: 1025px; "></div> (WARNING: The server did not provide any stacktrace information)

Cela se produit parce que la visionneuse obscurcit l'élément sur lequel je veux cliquer. Je souhaite attendre la disparition de la lightbox avant de cliquer sur le lien.

Vérifier que la lightbox n’existe plus n’est pas une solution de contournement valide car il existe parfois plusieurs niveaux de dialogues modaux et de lightbox, et il n’existe pas de moyen facile de les distinguer.

Y at-il un moyen dans Selenium de détecter si l’élément est cliquable (aucun autre élément ne l’obscurcit)? Un essai/attrapage serait une solution de contournement, mais je préférerais faire une vérification appropriée si cela est possible.

16
Matthew

Utilisez les conditions WebDriverWait.

    WebDriverWait wait = new WebDriverWait(yourWebDriver, 5);
    wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//xpath_to_element")));

Webdriver attendra 5 secondes pour que votre élément puisse être cliqué.

19
Pavel Zorin

Vous pouvez utiliser la méthode ExpectedConditions.invisibilityOfElementLocated(By by) qui attend que l'élément soit invisible ou non présent sur le DOM.

WebDriverWait wait = new WebDriverWait(yourWebDriver, 10);
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.id("yourSavingModalDialogDiv")));

Donc, selon le temps que prend votre dialogue modal pour devenir invisible ou pour quitter le DOM, WebDriver attend L’attente dure au maximum 10 secondes.

6
sreeharimohan

Vous pouvez créer une fonction/méthode clickUntil permettant à WebDriver d'attendre que l'élément puisse être cliqué avec un délai d'attente. Il essaierait de cliquer sur l'élément et d'éliminer les messages d'erreur "L'élément n'est pas cliquable" jusqu'à ce que vous obteniez un clic ou que le délai soit écoulé. 

Vous ne savez pas comment écrire cela dans le dojo, mais c'est une idée.

2
bbbco

J'ai aussi les mêmes problèmes, mais j'ai testé de nombreuses entrées sur le site. On est cliquable que j'ai testé et d'autres - non cliquable juste sauté. Je l'ai fait avec try () catch () Simply Code: 

for(){ // for all my input
try {
    driver.findElement(By.xpath("...."
                                + "//input)["+(i+1)+"]")).click();

  ... tests...


} catch(Exception e) {
     if(e.getMessage().contains("is not clickable at point")) {

          System.out.println(driver.findElement(By.xpath(locator)).
          getAttribute("name")+" are not clicable");
     } else {
          System.err.println(e.getMessage());
     }
}

Et plus élégant:

 @SuppressWarnings("finally")
       public boolean tryClick(WebDriver driver,String locator, locatorMethods m) {

           boolean result = false;
           switch (m) {

           case xpath:
            try {
                driver.findElement(By.xpath(locator)).click();
                result= true;
            } catch (Exception e) {
                   if(e.getMessage().contains("is not clickable at point")) {
                       System.out.println(driver.findElement(By.xpath(locator)).getAttribute("name")+" are not clicable");
                   } else {
                       System.err.println(e.getMessage());
                   }
            } finally {
                break;
            }
        case id:
            try {   
                driver.findElement(By.id(locator)).click();
                return true;
            } catch (Exception e) {
               if(e.getMessage().contains("is not clickable at point")) {
                   System.out.println(driver.findElement(By.id(locator)).getAttribute("name")+" are not clicable");   
               } else {
                   System.err.println(e.getMessage());
               }
            } finally {
                break;
            }

          default:
              System.err.println("Unknown locator!");

        }
           return result;
  }
0
Bartosz Gurgul

En Scala:

  1. Code standard pour l'attente (visibilité/invisibilité)

    (new WebDriverWait(remote, 45)).until(
        ExpectedConditions.visibilityOf(remote.findElement(locator))
    )
    Thread.sleep(3000)
    
  2. Plus de visibilité dans les logs: 

    while (remote.findElement(locator).isDisplayed) {
        println(s"isDisplayed: $ii $a : " + remote.findElement(locator).isDisplayed)
        Thread.sleep(100)
    }
    
  3. Si vous avez des processus JavaScript asynchrones, utilisez des éléments Web avec horodatage:

    val oldtimestamp = remote.findElements(locator).get(0).getAttribute("data-time-stamp")
    
    while (oldtimestamp == remote.findElements(locator).get(0).getAttribute("data-time-stamp")) {
        println("Tstamp2:" + remote.findElements(locator).get(0).getAttribute("data-time-stamp"))
        Thread.sleep(200)
    }
    
0
nexoma