diff --git a/src/client/network.ts b/src/client/network.ts index 02b620a0ab..81dbf742b8 100644 --- a/src/client/network.ts +++ b/src/client/network.ts @@ -442,12 +442,16 @@ export class WebSocket extends ChannelOwner { - const payload = event.opcode === 2 ? Buffer.from(event.data, 'base64') : event.data; - this.emit(Events.WebSocket.FrameSent, { payload }); + if (event.opcode === 1) + this.emit(Events.WebSocket.FrameSent, { payload: event.data }); + else if (event.opcode === 2) + this.emit(Events.WebSocket.FrameSent, { payload: Buffer.from(event.data, 'base64') }); }); this._channel.on('frameReceived', (event: { opcode: number, data: string }) => { - const payload = event.opcode === 2 ? Buffer.from(event.data, 'base64') : event.data; - this.emit(Events.WebSocket.FrameReceived, { payload }); + if (event.opcode === 1) + this.emit(Events.WebSocket.FrameReceived, { payload: event.data }); + else if (event.opcode === 2) + this.emit(Events.WebSocket.FrameReceived, { payload: Buffer.from(event.data, 'base64') }); }); this._channel.on('socketError', ({ error }) => this.emit(Events.WebSocket.Error, error)); this._channel.on('close', () => { diff --git a/tests/web-socket.spec.ts b/tests/web-socket.spec.ts index 5cbd4f653e..7cb84f59d7 100644 --- a/tests/web-socket.spec.ts +++ b/tests/web-socket.spec.ts @@ -72,6 +72,29 @@ it('should emit frame events', async ({ page, server }) => { expect(log.join(':')).toBe('close:open:received:sent'); }); +it('should filter out the close events when the server closes with a message', async ({ page, server }) => { + server.sendOnWebSocketConnection('incoming'); + let socketClosed; + const socketClosePromise = new Promise(f => socketClosed = f); + const log = []; + page.on('websocket', ws => { + log.push('open'); + ws.on('framesent', d => log.push('sent<' + d.payload + '>')); + ws.on('framereceived', d => log.push('received<' + d.payload + '>')); + ws.on('close', () => { log.push('close'); socketClosed(); }); + }); + await page.evaluate(port => { + const ws = new WebSocket('ws://localhost:' + port + '/ws-emit-and-close'); + ws.addEventListener('open', () => ws.send('outgoing')); + ws.addEventListener('message', () => { ws.close(); }); + }, server.PORT); + await socketClosePromise; + expect(log[0]).toBe('open'); + expect(log[3]).toBe('close'); + log.sort(); + expect(log.join(':')).toBe('close:open:received:sent'); +}); + it('should pass self as argument to close event', async ({ page, server }) => { let socketClosed; const socketClosePromise = new Promise(f => socketClosed = f); diff --git a/utils/testserver/index.js b/utils/testserver/index.js index 18d7e9f63d..cab7254499 100644 --- a/utils/testserver/index.js +++ b/utils/testserver/index.js @@ -69,10 +69,17 @@ class TestServer { else this._server = http.createServer(this._onRequest.bind(this)); this._server.on('connection', socket => this._onSocket(socket)); - this._wsServer = new WebSocketServer({server: this._server, path: '/ws'}); - this._wsServer.on('connection', ws => { + this._wsServer = new WebSocketServer({server: this._server }); + this._wsServer.shouldHandle = (request) => { + const pathname = url.parse(request.url).pathname; + return ['/ws', '/ws-emit-and-close'].includes(pathname); + }; + this._wsServer.on('connection', (ws, request) => { + const pathname = url.parse(request.url).pathname; if (this._onWebSocketConnectionData !== undefined) ws.send(this._onWebSocketConnectionData); + if (pathname === '/ws-emit-and-close') + ws.close(1003, 'closed by Playwright test-server'); }); this._server.listen(port); this._dirPath = dirPath;