My problem is as follows. I have several links on the page, which I must follow, and then return to the same page. I tried to do it in the following way:
const els = await page.$$('div[name="olymp"] a'); // get links on the page
for (let i = 0; i < els.length; i++) {
await els[i].click(); // clicking on a link that leads to another page
await page.waitForLoadState('networkidle');
await page.click('div.floating:nth-child(1)');
await page.click('div.floating:nth-child(1) div.extra a') // a link on another page that leads to the first page
}
And i got error on second iteration:
elementHandle.click: Protocol error (DOM.describeNode): Cannot find context with specified id
Maybe someone came across a similar one?
im using Playwright v1.13
The issue is on the second iteration through the loop, the element handle has been disposed. In both playwright & puppeteer resources get dumped after page commits navigation. Rather than operating on each element handle, try something like this:
const linksCount = await page.$$eval('div[name="olymp"] a', (links) => links.length);
for (let i = 0; i < linksCount; i += 1) {
await Promise.all([
page.$$eval('div[name="olymp"] a', links => links[i].click()),
page.waitForLoadState('networkidle')
]);
await page.click('div.floating:nth-child(1)');
await Promise.all([
page.click('div.floating:nth-child(1) div.extra a'),
page.waitForLoadState('networkidle')
]);
}
Note you may want to use page.waitForNavigation
rather than page.waitForLoadState
if in fact clicking those links leads to a navigation/page reload. Anytime you are performing some action which triggers a navigation (like clicking a link), its considered good practice to wrap it with Promise.all
like in the above in order to prevent race conditions.
Source:
https://playwright.dev/docs/api/class-page#page-wait-for-navigation https://github.com/puppeteer/puppeteer/issues/2258