Closed othree closed 6 years ago
Is there a way to detect that navigation is complete in Puppeteer?
There is a page.waitForNavigation
method mentioned in GoogleChrome/puppeteer#1325 , I didn't tested yet. And it will have another problem, some click didn't trigger navigation. Or maybe codecept can expose it to outside.
I've just spent a bit of time looking into this and it is slightly more complex than I thought. Though I found some useful information on the puppeter repo.
It looks like that you have to call the .click
and page.waitForNavigation
at the same time like so:
await Promise.all([
page.click('a'),
page.waitForNavigation()
]);
The reason that it needs to be called at the same time is that apparently .waitForFunction needs to see the new page trigger and the load events occur. So just seeing the page load event is not enough.
So our problem is that we don't know which links will cause a new page to load. And if the above code is used and the link does not change the url, then it will throw a timeout error.
Now we could check the button if it is link like, however that does not cater for the scenario if there are event handlers on it which cause a redirect somewhere. So here are some options.
However I have been playing around with the idea with using the targetchanged
and load
events, and recording the url has changed and loaded
state information. So the scenario would play out like this:
targetchanged
event to trigger). targetchanged
event triggers, and sets a urlChanged flagload
event triggers, reset the urlChanged flag.Maybe using I.waitInUrl
or something similar to that...
Thoughts?
I am using a work around similar to option 2.
navByClick (text, locator) {
this.click(text, locator);
this.wait(2);
},
Not a good one, but works for my test.
And I think the final solution for this issue need to wait until puppeteer solves 1325. So add a method might become unnecessary in the future. Maybe it will depend on how codeceptjs decide to add a new helper method or not.
I have update my work around by extend helper:
/* global codecept_helper */
'use strict';
let Helper = codecept_helper;
class MyPuppeteer extends Helper {
async navByClick (text, locator) {
await this.helpers['Puppeteer'].click(text, locator);
const page = this.helpers['Puppeteer'].page;
await Promise.race([page.waitForNavigation({waitUntil: 'networkidle0'}), this.helpers['Puppeteer'].wait(4)]);
}
}
module.exports = MyPuppeteer;
And helper section in codecept.json:
"helpers": {
"Puppeteer": {
"disableScreenshots": false,
"waitForAction": 800,
"show": true
},
"MyPuppeteer": {
"require": "./test/my_puppeteer.js"
}
},
Promise.race
is due to GoogleChrome/puppeteer#1936 ...
Should be fixed in #936
I just ran into the same problem with Puppeteer 1.3.0 (not 0.13.0 as in some comments on #1325). I already had await page.waitForNavigation();
following the await btn.click();
. The await Promise.all ...
solution in @reubenmiller 's Feb. 7 comment resolved it. I haven't checked if it's necessary, but I still have the additional waitForNavigation()
after it.
I am seeing something similar on 1.3.0-next.1525301631811
(node:10626) UnhandledPromiseRejectionWarning: Error: Protocol error (Runtime.evaluate): Cannot find context with specified id undefined
at Promise (/home/luke/git/flowcrypt-browser/test/node_modules/puppeteer/lib/Connection.js:200:56)
at new Promise (<anonymous>)
at CDPSession.send (/home/luke/git/flowcrypt-browser/test/node_modules/puppeteer/lib/Connection.js:199:12)
at ExecutionContext.evaluateHandle (/home/luke/git/flowcrypt-browser/test/node_modules/puppeteer/lib/ExecutionContext.js:67:77)
at _documentPromise._contextPromise.then (/home/luke/git/flowcrypt-browser/test/node_modules/puppeteer/lib/FrameManager.js:346:38)
at <anonymous>
There is no navigation, just looking for elements in a loop:
for (let i = 0; i < selectors.length; i++) {
let elements = this._is_xpath(selectors[i]) ? await page.$x(selectors[i]) : await page.$$(selectors[i]);
// ...
}
What are you trying to achieve?
click
see
text from new pageWhat do you get instead?
Got this error and test failed.
Details
PS. It related to the value of
waitForAction
. If change it to larger. error will not happen.More Information
This issue is related to GoogleChrome/puppeteer#1325.
And I think latest comment is correct. The problem is because the click promise resolved when click triggered. But at that moment, navigation is not complete. No context is ready for new action.