'Why does frame selection breaks after page reloads?
I am trying to inspect a page with playwright that holds a frame document that when I click a button a banner will appear for a couple of minutes. When it's done the page needs to be reloaded for the banner to disappear. I am checking every 5 minutes automatically until I don't see the banner on the page but when I can only do it for the 1 loop after that the code breaks. What can I do to fix this.
A possible solution could be going to the iframe link itself but the document breaks if I do that. I wish to avoid doing this. It's not how I would do things if I was manually doing this.
UnhandledPromiseRejectionWarning: frame.evaluate: Execution Context is not available in detached frame (are you trying to evaluate?)
const browser = await chromium.launch({
args: ["--start-maximized", "--disable-notifications", '--disable-extensions', '--mute-audio'],
defaultViewport: null,
devtools: true,
slowMo: 50,
downloadsPath: "D:\\Lambda\\projects\\puppeteer_test\\data",
});
// Create a new incognito browser context with user credentials
const context = await browser.newContext({
acceptDownloads: true,
viewport: null,
storageState: JSON.parse(storageState),
})
// Create a new page in a pristine context.
const page = await context.newPage()
// go to download your information
await page.goto("");
//select child frame
const frameDocUrl = await (await page.waitForSelector("iframe")).getAttribute("src")
const doc = await page.frame({url: frameDocUrl})
await doc.waitForLoadState('domcontentloaded');
/* waitForFile */
// refresh every 5 minute until notice of gathering file is gone
// then Pending becomes download
const frameUrl = await doc.url()
const fiveMinutes = 300000
let IsGatheringFile = await doc.$("//div[text()='A copy of your information is being created.']") ? true: false
while(IsGatheringFile){
//reload page
console.log("going to reload")
await doc.goto(frameUrl)
// wait for 5 minutes
console.log(`going to start waiting for 5 min starting in ${Date().split(" ")[4]}`)
await doc.waitForTimeout(fiveMinutes)
console.log("finish reloading")
// check if notice is gone
IsGatheringFile = await doc.$("//div[text()='A copy of your information is being created.']") ? true: false
}
console.log("finish waiting for data")
console.log("finish reloading the page until the banner is gone")
Solution 1:[1]
Solution: after the page refresh/new navigation recapture the focus on the iframe.
const frameUrl = await doc.url()
await doc.goto(frameUrl)
Also, note that you can update the variable that you are passing by to the other parts of your script with the new refresh iframe.
old hacky fix:
Instead of reloading the page reload the iframe.
At the moment there is no frame.reload but this process can be achieved by frame.goto(frameURL)
const frameUrl = await doc.url()
await doc.goto(frameUrl)
Note: iframe can break. Reloading the page can fix it but the frame will be detached.
Solution 2:[2]
This post is a bit old but I will respond anyway as I had this problem this week and just resolved it.
I am in python not Node, but the logic is still the same I believe.
So for me, just recapturing the focus didn't work after the page.reload().
I did use the "old hacky fix" and instead of reload all the page, reloaded just the frame concerned. My solution is like that :
iframe.goto(iframe.url)
is_detached = iframe.is_detached()
if is_detached:
iframe = page.main_frame.child_frames[-1]
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Medusa |