web-dev-qa-db-fra.com

Marionnettiste: attendre qu'un élément soit visible?

J'aimerais savoir si je peux dire au marionnettiste d'attendre qu'un élément soit affiché.

const inputValidate = await page.$('input[value=validate]');
await inputValidate.click()

//I want to do something like that 
waitElemenentVisble('.btnNext ')

const btnNext = await page.$('.btnNext');
await btnNext.click();

Y at-il un moyen que je peux accomplir cela?

23
Vivien Pipo

Je pense que vous pouvez utiliser la fonction page.waitForSelector(selector[, options]) à cette fin.

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  page
    .waitForSelector('#myId')
    .then(() => console.log('got it');
  browser.close();
});
27
turmuka

Remarque, la réponse ci-dessus est incorrecte!

Parce qu'il répond pour un élément si existe ou se trouve but NOT visible ou affiché

La bonne solution consiste à vérifier la taille ou la visibilité d'un élément à l'aide de page.waitFor() ou page.waitForFunction() , voir l'explication ci-dessous.

// wait until present on the DOM
// await page.waitForSelector( css_selector );
// wait until "display"-ed
await page.waitForFunction("document.querySelector('.btnNext') && document.querySelector('.btnNext').clientHeight != 0");
// or wait until "visibility" not hidden
await page.waitForFunction("document.querySelector('.btnNext') && document.querySelector('.btnNext').style.visibility != 'hidden'");

const btnNext = await page.$('.btnNext');
await btnNext.click();

Explication

L'élément qui existe sur le DOM de la page n'est pas toujours visible si possède la propriété CSS display:none Ou visibility:hidden, Raison pour laquelle utiliser page.waitForSelector(selector) n'est pas une bonne idée. extrait ci-dessous.

function isExist(selector) {
  let el = document.querySelector(selector);
  let exist = el.length != 0 ? 'Exist!' : 'Not Exist!';
  console.log(selector + ' is ' + exist)
}

function isVisible(selector) {
  let el = document.querySelector(selector).clientHeight;
  let visible = el != 0 ? 'Visible, ' + el : 'Not Visible, ' + el;
  console.log(selector + ' is ' + visible + 'px')
}

isExist('#idA');
isVisible('#idA');
console.log('=============================')
isExist('#idB')
isVisible('#idB')
.bd {border: solid 2px blue;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="bd">
  <div id="idA" style="display:none">#idA, hidden element</div>
</div>
<br>
<div class="bd">
  <div id="idB">#idB, visible element</div>
</div>

sur l'extrait de code au-dessus de la fonction isExist() simule

page.waitForSelector('#myId');

et nous pouvons voir en exécutant isExist() pour les deux éléments #idA un #idB est de retour existe.

Mais lors de l'exécution de isVisible(), le #idA N'est ni visible ni masqué.

Et voici d'autres objets pour vérifier si un élément est affiché ou en utilisant la propriété CSS display.

scrollWidth
scrollHeight
offsetTop
offsetWidth
offsetHeight
offsetLeft
clientWidth
clientHeight

pour le style visibility cocher non hidden.

note: Je ne suis pas bon en Javascript ou en anglais, n'hésitez pas à améliorer cette réponse.

17
ewwink

Si vous voulez vous assurer que l'élément est réellement visible, vous devez utiliser

page.waitForSelector('#myId', {visible: true})

Sinon, vous recherchez uniquement l'élément dans le DOM et ne recherchez pas la visibilité.

12
finn

Vous pouvez utiliser page.waitFor() , page.waitForSelector() ou page.waitForXPath() attendre pour un élément sur un page :

// Selectors

const css_selector   = '.btnNext';
const xpath_selector = '//*[contains(concat(" ", normalize-space(@class), " "), " btnNext ")]';

// Wait for CSS Selector

await page.waitFor( css_selector );
await page.waitForSelector( css_selector );

// Wait for XPath Selector

await page.waitFor( xpath_selector );
await page.waitForXPath( xpath_selector );

Remarque: En référence à un frame , vous pouvez également utiliser frame.waitFor() =, frame.waitForSelector() , ou frame.waitForXPath() .

7
Grant Miller

Réponse mise à jour avec quelques optimisations:

const puppeteer = require('puppeteer');

(async() => {
    const browser = await puppeteer.launch({headless: true});
    const page = await browser.newPage();

    await page.goto('https://www.somedomain.com', {waitUntil: 'networkidle2'});
    await page.click('input[value=validate]');
    await page.waitForSelector('#myId');
    await page.click('.btnNext');
    console.log('got it');

    browser.close();
})();
3
luschn