How to wait for JavaScript to finish in playwright

Viewed 22691

I am testing UI with Playwright and JavaScript. My code find an input element that can sometimes be a drop down, sometimes a text and sometimes a date. To handle this I enter value with 2 steps. First I fill the text and then click on tab key to invoke the JavaScript that formats the value in the element.

await page.fill("#myID", inputText); 
await page.keyboard.press('Tab');  // this line trigger the JS

// continue to the next element 

The problem, it is not waiting for JavaScript to finish. How can I wait for JS to finish before the code continue.

3 Answers

Using the page.waitFor... functions

There are a slew of functions that playwright offers for when certain conditions are met that start with page.waitFor (e.g. page.waitForFunction). Probably page.waitForFunction is the most versatile, because you can pass a custom function that waits for a specific condition to be met.

Alternatively, use a timeout

I think you can use setTimeout with page.evaluate inside the page context to wait a bit for other JavaScript to run:

await page.evaluate(() => {
  // if this doesn't work, you can try to increase 0 to a higher number (i.e. 100)
  return new Promise((resolve) => setTimeout(resolve, 0));
});

This might be equivalent to page.waitForTimeout(0), but I'm not sure. Note that they recommend not to use page.waitForTimeout in production.

You could wait for some reaction to your click (some page change, or HTTP request made), for example:

You might find this useful, (https://repl.it/join/bkgmwcjv-vladimirlisove1). https://developer.mozilla.org/enUS/docs/Web/JavaScript/Reference/Statements/async_function.

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  const result = await resolveAfter2Seconds();
  console.log(result);
  // expected output: "resolved"
}

asyncCall();

alternatively, found an example from freecodecamp, which appears to be simpler:

const promise = new Promise((resolve, reject) => {  

  setTimeout(function(){ 
    resolve(); // Task is completed
  }, 3000);

  return resolve;
});

promise.then(res => {
  console.log('resolved');
}).catch(err => {
    console.log(err)
});
Related