web-dev-qa-db-fra.com

Selenium WebDriver attend que l'élément soit affiché

J'ai effectué une recherche sur Google et sur le site SO et j'obtiens des réponses pour Java mais ne semble pas en obtenir pour node.js

J'ai une application Web qui prend du temps à charger. Je voudrais programme Selenium pour attendre que la page est chargée et ensuite effectuer certaines actions.

Mon code actuel est le suivant

//dependencies
var webdriver = require('Selenium-webdriver'),
    util = require('util'),
    _ = require('underscore');

var driver = new webdriver.Builder().withCapabilities(webdriver.Capabilities.chrome()).build();
var branchName =  _.isUndefined(process.argv[3]) ? 'branch' : process.argv[3], 
    hostName = _.isUndefined(process.argv[2]) ? 'localhost' : process.argv[2],
    appTmpl = 'http://%s/%s',
    username = 'xxxx',
    password = 'xxxx';
var appUrl = util.format(appTmpl, hostName, branchName);

driver.get(appUrl);
driver.findElement(webdriver.By.name("username")).sendKeys(username);
driver.findElement(webdriver.By.name("password")).sendKeys(password);
driver.findElement(webdriver.By.name("login_button")).click();
driver.quit();

L'erreur que je reçois est:

    C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\promise.js:1643
      throw error;
            ^
NoSuchElementError: no such element
  (Session info: chrome=37.0.2062.103)
  (Driver info: chromedriver=2.10.267521,platform=Windows NT 6.1 SP1 x86_64)
    at new bot.Error (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\atoms\error.js:109:18)
    at Object.bot.response.checkResponse (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\atoms\response.js:106:9)
    at C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\webdriver.js:277:20
    at C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\goog\base.js:1243:15
    at webdriver.promise.ControlFlow.runInNewFrame_ (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\promise.js:1539:20)
    at notify (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\promise.js:362:12)
    at notifyAll (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\promise.js:331:7)
    at resolve (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\promise.js:309:7)
    at fulfill (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\promise.js:429:5)
    at C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\promise.js:1406:10
==== async task ====
WebDriver.findElement(By.name("username"))
    at webdriver.WebDriver.schedule (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\webdriver.js:268:15)
    at webdriver.WebDriver.findElement (C:\Work\study\Selenium\node_modules\Selenium-webdriver\lib\webdriver\webdriver.js:711:17)
    at Object.<anonymous> (C:\Work\study\Selenium\test.js:15:8)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)
    at startup (node.js:119:16)
33
Anand Sunderraman

Je suis tombé sur une réponse à ma question

Donc, pour attendre qu'un élément apparaisse, nous devons:

driver.wait(function () {
    return driver.isElementPresent(webdriver.By.name("username"));
}, timeout);
39
Anand Sunderraman

Vous pouvez enregistrer un auditeur sur webdriver.wait en utilisant then()

return driver.wait(until.elementLocated(By.name('username')), 5 * 1000).then(el => {
    return el.sendKeys(username);
});
24
Joe Coder

Vous n'avez pas besoin d'une fonction personnalisée, vous pouvez simplement faire ceci:

  let el = await driver.findElement(By.id(`import-file-acqId:${acqId}`));
  await driver.wait(until.elementIsVisible(el),100);
  await el.sendKeys(file);

Voir les docs ici:

https://seleniumhq.github.io/Selenium/docs/api/javascript/module/Selenium-webdriver/lib/until.html

15
Alexander Mills

Essayez quelque chose comme ça:

function isItThere(driver, element){

    driver.findElement(webdriver.By.id(element)).then(function(webElement) {
            console.log(element + ' exists');
        }, function(err) {
            if (err.state && err.state === 'no such element') {
                console.log(element + ' not found');
            } else {
                webdriver.promise.rejected(err);
            }
        });
}

Je l'ai adapté légèrement en fonction de ce que j'ai trouvé ici: Vérifier si l'élément existe - Selenium/javascript/node-js et cela a fonctionné avec charme.

3
QualiT

C'est la seule chose qui fonctionne pour moi:

const element = By.id('element');
driver.wait(until.elementLocated(element));
const whatElement = driver.findElement(element);
driver.wait(until.elementIsVisible(whatElement), 5000).click();
2
Christopher Grigg

J'utilise habituellement de cette façon:

 var el = driver.wait(until.elementLocated(By.name('username')));
el.click();
1
Tadeu Rangel

Écriture fonction asynchrone pour éviter ce problème

(async function() {
  let url = args[0];
  await driver.get(url);
  driver.quit();
})();
0
Tamil

J'ai proposé cette approche car elle maintient la syntaxe chainable de promesse pour que je puisse écrire ceci: await waitFind(By.id('abc')).click()

const waitFind = (locator) => {
    return driver.findElement(async () => {
        await driver.wait(until.elementLocated(locator));
        return driver.findElement(locator);
    });
}
0
James H