-
Notifications
You must be signed in to change notification settings - Fork 9.3k
feat(browser): add browser.disconnected event #960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
this just take one point on existing issues. Out of contextMy attempt was add beforeEach block under Page.close suite, but the linting yell |
docs/api.md
Outdated
| ``` | ||
|
|
||
| #### event: 'closed' | ||
| Emitted when page closed or crashed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Emitted when page gets closed or page renderer crashes.
lib/Page.js
Outdated
| return this.mainFrame().title(); | ||
| } | ||
|
|
||
| _closed() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's inline this method
test/test.js
Outdated
| it('should emmited when page got crashed', SX(async function() { | ||
| let emitted = false; | ||
| page.on('closed', () => emitted = true); | ||
| page.goto('chrome://crash'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should be able to await page.goto here, instead of doing the waitForEvents on the following line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it fail on my machine if i do await page.goto(url); , with jasmine timeout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here the travis test failure. That's why i wait on error, maybe you can assist me?
|
@aslushnikov dude, i need help on browser.closed, when it crashes. I have no idea how to make the browser crashes and how to make spec about it. I already trying a couple of hour but no result. |
|
@brutalcrozt the page |
|
@ebidel Thanks Eric, i notice that now. But surely i still don't know how to make |
|
Since now we get
|
lib/Browser.js
Outdated
| } | ||
|
|
||
| Browser.Events = { | ||
| Closed: 'closed' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be called 'disconnected' and should be emitted whenever the connection is closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, thanks for put a trust in me.
lib/Page.js
Outdated
| } | ||
|
|
||
| _onTargetCrashed() { | ||
| this._closed(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there should be no need to emit the error event now; it should be just 'crashed'
lib/Page.js
Outdated
| return this.mainFrame().title(); | ||
| } | ||
|
|
||
| _closed() { this.emit(Page.Events.Closed, 'page closed'); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the 'closed' event is not needed any more since we have target events; they should cover everything
|
@aslushnikov IDK why this PR fail on node 7 when running yarn run lint. |
lib/Browser.js
Outdated
|
|
||
| disconnect() { | ||
| this._connection.dispose(); | ||
| this._disconnected(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the event should also be fired whenever the connection itself gets disconnected (e.g. whenever the browser gets closed)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aslushnikov Sorry, i don't get it. Could you re-explain it to me? 😕
lib/Browser.js
Outdated
| return version.product; | ||
| } | ||
|
|
||
| _disconnected() { this.emit(Browser.Events.Disconnected, 'connection disconnected');} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: formatting here is improper. The "inlining" is to remove the function _disconnected and just emit the event in disconnected method right away.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
|
ping @aslushnikov for review |
lib/Browser.js
Outdated
|
|
||
| disconnect() { | ||
| this._connection.dispose(); | ||
| this.emit(Browser.Events.Disconnected, 'connection disconnected'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this event should be emitted when the browser gets closed; e.g. when it crashes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, let me know if it still wrong. So it's introduce breaking changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, I think there's some miscommunication here.
I actually meant the browser crash, not the page crash.
The only signal we get when the browser crashes is the disconnect of web socket (see lib/Connection.js). We should capture this event and dispatch the disconnected for it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, we take a look on it. I also need your advice to reflect the documentation changes for this one. FYI build fail because travis are down.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hope that was the right one, i skip the test for this case.
test/test.js
Outdated
| newBrowser.disconnect(); | ||
| expect(isDisconnected).toBe(true); | ||
| })); | ||
| xit('should be emitted when underlying websocket gets closed', SX(async function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should be able to:
- launch a browser
- connect to it with
pptr.connect - close the browser, make sure the connected one issues the
disconnectedevent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me know if it still not fit, is that a parrot in your profile picture?
lib/Browser.js
Outdated
| return version.product; | ||
| } | ||
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: stray line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lib/Browser.js
Outdated
| /** @type {Map<string, Target>} */ | ||
| this._targets = new Map(); | ||
| this._connection.on('ws.closed', closed => { | ||
| this.disconnect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to run this.disconnect() here - you only need to emit the event.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
docs/api.md
Outdated
| }); | ||
| ``` | ||
| #### event: 'disconnected' | ||
| emitted whenever the connection is closed `Browser.close() Browser.disconnect()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure this one, let me know if any better suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're getting close!
docs/api.md
Outdated
| }); | ||
| ``` | ||
| #### event: 'disconnected' | ||
| emitted whenever the connection is closed `Browser.close() Browser.disconnect()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's do the following wording:
Emitted when puppeteer gets disconnected from the browser instance. This might happen because one of the following:
- browser closed or crashed
browser.disconnectmethod was called
lib/Browser.js
Outdated
| this._closeCallback = closeCallback || new Function(); | ||
| /** @type {Map<string, Target>} */ | ||
| this._targets = new Map(); | ||
| this._connection.on('ws.closed', closed => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we shouldn't whitelist certain events and give them special treatment.
Instead, let's introduce a "closedCallback" for the connection and initialize it here:
this._connection.setClosedCallback(() => {
this.emit(Browser.Events.Disconnected);
});
lib/Browser.js
Outdated
| /** @type {Map<string, Target>} */ | ||
| this._targets = new Map(); | ||
| this._connection.on('ws.closed', closed => { | ||
| this.emit(Browser.Events.Disconnected, 'connection disconnected'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's drop the argument for the event, it's unclear if it's useful.
lib/Browser.js
Outdated
|
|
||
| disconnect() { | ||
| this._connection.dispose(); | ||
| this.emit(Browser.Events.Disconnected, 'connection disconnected'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to emit here: this will result in disconnected event dispatched twice (one from here, another from the connection been closed)
lib/Connection.js
Outdated
|
|
||
| _onClose() { | ||
| _onClose(code, reason) { | ||
| if (code) this.emit('ws.closed', [code, reason]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- let's emit as the very last line in the method. This way, if there's an exception in user-land code, we won't be left in a non-consistent state.
- We should emit unconditionally
- Let's not emit any details for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, hopefully i am not misunderstand again.
test/test.js
Outdated
| isDisconnected = true; | ||
| }); | ||
| newBrowser.disconnect(); | ||
| expect(isDisconnected).toBe(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please, close originalBrowser here so that it's not left dangling
test/test.js
Outdated
| isDisconnected = true; | ||
| resolver(); | ||
| }); | ||
| browser._connection._ws.close(3006, 'intentionally kill it'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should not reach to private variables in tests.
Instead, this test could be written like the previous one, but instead of disconnecting
the new browser, closing original one:
it('should be emitted when underlying websocket gets closed', SX(async function() {
const browser = await puppeteer.launch(defaultBrowserOptions);
const newBrowser = await puppeteer.connect({
browserWSEndpoint: originalBrowser.wsEndpoint()
});
let isDisconnected = false;
newBrowser.once('disconnected', () => isDisconnected = true);
await originalBrowser.close();
expect(isDisconnected).toBe(true);
}));There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry i didn't know that, i just try to get closer to
should be emitted when underlying websocket gets closed
Most of my time yesterday was spend here, i wish know it earlier. Next time i should be more clever on testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@brutalcrozt feel free to ask questions next time if you're getting stuck.
lib/Connection.js
Outdated
| } | ||
|
|
||
| module.exports = {Connection, Session}; | ||
| /** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these different line-endings? Can you please revert the change so that the actual changes are clear?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps, certainly i will do.
test/test.js
Outdated
| }); | ||
|
|
||
| describe('Browser.Events.disconnected', function() { | ||
| it('should emitted when browser gets closed', SX(async function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this one fired disconnected twice, i notice that. Same effect when i use the browser, Assuming it added to two instance the browser and originalBrowser. For me it's important you to know. If i am wrong please leave some suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
That's because:
- Connection should reset it's
this._wstonullonce the COnnection._onClose method is called. - Connection._onClose should remove added event listeners (use
helper.addEventListener/helper.removeEventListenersfor this) - The Connection.dispose() method should fast-return if this._ws === null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not fully understand it, but i do the trick. Hopefully good to go 😄
|
@aslushnikov This one is ready captain. 😄 |
|
|
||
| /** | ||
| * @param {function()} callback | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you please format this?
setClosedCallback(callback) {
this._closeCallback = callback;
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, so no inline on class method? Inline only on normal code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Inlining" is not about code formatting.
To "inline a function" means to get the function body and paste it instead of function invocations.
More on wiki: inline expanstion
lib/Connection.js
Outdated
| } | ||
|
|
||
| _onClose() { | ||
| this._closeCallback(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- this should be the last line in the method
- for the sake of cleanliness, let's check that delegate is set:
if (this._closeCallback)
this._closeCallback();
test/test.js
Outdated
| }); | ||
|
|
||
| describe('Browser.Events.disconnected', function() { | ||
| it('should emitted when browser gets closed', SX(async function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
That's because:
- Connection should reset it's
this._wstonullonce the COnnection._onClose method is called. - Connection._onClose should remove added event listeners (use
helper.addEventListener/helper.removeEventListenersfor this) - The Connection.dispose() method should fast-return if this._ws === null.
test/test.js
Outdated
| await originalBrowser.close(); | ||
| expect(isDisconnected).toBe(true); | ||
| })); | ||
| it('should emitted when browser.disconnect() called', SX(async function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's unify these three tests into one. This will save us on some time while running tests.
const originalBrowser = await puppeteer.launch(defaultBrowserOptions);
const browserWSEndpoint = originalBrowser.wsEndpoint();
const remoteBrowser1 = await puppeteer.connect({browserWSEndpoint});
const remoteBrowser2 = await puppeteer.connect({browserWSEndpoint});
let disconnectedOriginal = 0;
let disconnectedRemote1 = 0;
let disconnectedRemote2 = 0;
originalBrowser.on('disconnected', () => ++disconnectedOriginal);
remoteBrowser1.on('disconnected', () => ++disconnectedRemote1);
remoteBrowser2.on('disconnected', () => ++disconnectedRemote2);
await remoteBrowser2.disconnect();
expect(disconnectedOriginal).toBe(0);
expect(disconnectedRemote1).toBe(0);
expect(disconnectedRemote2).toBe(1);
await originalBrowser.close();
expect(disconnectedOriginal).toBe(1);
expect(disconnectedRemote1).toBe(1);
expect(disconnectedRemote2).toBe(1);|
Thanks! |
This patch add browser.disconnected event :
fix Add
browser.closedandpage.closedevents #952