I have an HTML table with data like
| Username | is admin | Actions |
|---|---|---|
| New User | ✓ | Make Admin |
| Old User | Make Admin |
After clicking "Make Admin", how do I wait for the check mark to show up?
I figured out how to look for the checkmark:
const checkmarkText = await page.$eval(`text/${new_user}`, e=>{
return e.nextSibling.innerHTML;
});
But I'm not sure how to do a .waitForSelector(???) waiting for this checkmark.
For what it's worth, the HTML is very simple like this:
<tr>
<td>
New User
</td>
<td>
✓
</td>
<td>
...
</td>
</tr>
You can use page.waitForFunction to wait for an arbitrary predicate like this.
Here's the site we're testing. After 2 seconds the checkmark appears:
<!DOCTYPE html><html><body>
<table><tbody><tr>
<td>
New User
</td>
<td>
</td>
<td>
...
</td>
</tr></tbody></table>
<script>
setTimeout(() => {
const td = [...document.querySelectorAll("td")][1];
td.textContent = "✓";
}, 2000);
</script></body></html>
Here's the full code to wait for this checkmark:
const puppeteer = require("puppeteer"); // ^24.20.0
const html = `<!DOCTYPE html><html><body>
<table><tbody><tr>
<td>
New User
</td>
<td></td>
<td>...</td>
</tr></tbody></table><script>
setTimeout(() => {
const td = [...document.querySelectorAll("td")][1];
td.textContent = "✓";
}, 2000);
</script></body></html>`;
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.setContent(html);
console.log("waiting for checkmark...");
await page.waitForFunction((newUser) => {
const newUserEl = [...document.querySelectorAll("td")]
.find(el => el.textContent.trim() === newUser);
return newUserEl?.nextElementSibling?.textContent?.trim() === "✓";
}, {}, "New User");
console.log("checkmark is guaranteed to exist at this point");
})()
.catch(err => console.error(err))
.finally(() => browser?.close());