diff --git a/lib/websocket/events.js b/lib/websocket/events.js index a1d3a676cd4..621a2263b7d 100644 --- a/lib/websocket/events.js +++ b/lib/websocket/events.js @@ -11,6 +11,8 @@ class MessageEvent extends Event { #eventInit constructor (type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'MessageEvent constructor' }) + type = webidl.converters.DOMString(type) eventInitDict = webidl.converters.MessageEventInit(eventInitDict) @@ -80,6 +82,8 @@ class CloseEvent extends Event { #eventInit constructor (type, eventInitDict = {}) { + webidl.argumentLengthCheck(arguments, 1, { header: 'CloseEvent constructor' }) + type = webidl.converters.DOMString(type) eventInitDict = webidl.converters.CloseEventInit(eventInitDict) @@ -117,9 +121,7 @@ class ErrorEvent extends Event { super(type, eventInitDict) type = webidl.converters.DOMString(type) - if (eventInitDict !== undefined) { - eventInitDict = webidl.converters.ErrorEventInit(eventInitDict) - } + eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {}) this.#eventInit = eventInitDict } diff --git a/test/websocket/close.js b/test/websocket/close.js index 100e1f404de..4d314a4f4c4 100644 --- a/test/websocket/close.js +++ b/test/websocket/close.js @@ -5,7 +5,7 @@ const { WebSocketServer } = require('ws') const { WebSocket } = require('../..') test('Close', (t) => { - t.plan(5) + t.plan(6) t.test('Close with code', (t) => { t.plan(1) @@ -109,4 +109,22 @@ test('Close', (t) => { const ws = new WebSocket(`ws://localhost:${server.address().port}`) ws.addEventListener('open', () => ws.close()) }) + + t.test('Close with a 3000 status code', (t) => { + t.plan(2) + + const server = new WebSocketServer({ port: 0 }) + + server.on('connection', (ws) => { + ws.on('close', (code, reason) => { + t.equal(code, 3000) + t.same(reason, Buffer.alloc(0)) + }) + }) + + t.teardown(server.close.bind(server)) + + const ws = new WebSocket(`ws://localhost:${server.address().port}`) + ws.addEventListener('open', () => ws.close(3000)) + }) }) diff --git a/test/websocket/constructor.js b/test/websocket/constructor.js index 7e8e4c86aff..a09515868c8 100644 --- a/test/websocket/constructor.js +++ b/test/websocket/constructor.js @@ -44,5 +44,13 @@ test('Constructor', (t) => { } ) + t.throws( + () => new WebSocket('wss://echo.websocket.events', ['<>@,;:\\"/[]?={}\t']), + { + name: 'SyntaxError', + constructor: DOMException + } + ) + t.end() }) diff --git a/test/websocket/events.js b/test/websocket/events.js new file mode 100644 index 00000000000..89e4e0ba353 --- /dev/null +++ b/test/websocket/events.js @@ -0,0 +1,101 @@ +'use strict' + +const { test } = require('tap') +const { WebSocketServer } = require('ws') +const { MessageEvent, CloseEvent, ErrorEvent } = require('../../lib/websocket/events') +const { WebSocket } = require('../..') + +test('MessageEvent', (t) => { + t.throws(() => new MessageEvent(), TypeError, 'no arguments') + t.throws(() => new MessageEvent('').initMessageEvent(), TypeError) + + const noInitEvent = new MessageEvent('message') + + t.equal(noInitEvent.origin, '') + t.equal(noInitEvent.data, null) + t.equal(noInitEvent.lastEventId, '') + t.equal(noInitEvent.source, null) + t.ok(Array.isArray(noInitEvent.ports)) + t.ok(Object.isFrozen(noInitEvent.ports)) + t.type(new MessageEvent('').initMessageEvent('message'), MessageEvent) + + t.end() +}) + +test('CloseEvent', (t) => { + t.throws(() => new CloseEvent(), TypeError) + + const noInitEvent = new CloseEvent('close') + + t.equal(noInitEvent.wasClean, false) + t.equal(noInitEvent.code, 0) + t.equal(noInitEvent.reason, '') + + t.end() +}) + +test('ErrorEvent', (t) => { + t.throws(() => new ErrorEvent(), TypeError) + + const noInitEvent = new ErrorEvent('error') + + t.equal(noInitEvent.message, '') + t.equal(noInitEvent.filename, '') + t.equal(noInitEvent.lineno, 0) + t.equal(noInitEvent.colno, 0) + t.equal(noInitEvent.error, undefined) + + t.end() +}) + +test('Event handlers', (t) => { + t.plan(4) + + const server = new WebSocketServer({ port: 0 }) + const ws = new WebSocket(`ws://localhost:${server.address().port}`) + + function listen () {} + + t.teardown(server.close.bind(server)) + t.teardown(() => ws.close()) + + t.test('onopen', (t) => { + t.plan(3) + + t.equal(ws.onopen, null) + ws.onopen = 3 + t.equal(ws.onopen, null) + ws.onopen = listen + t.equal(ws.onopen, listen) + }) + + t.test('onerror', (t) => { + t.plan(3) + + t.equal(ws.onerror, null) + ws.onerror = 3 + t.equal(ws.onerror, null) + ws.onerror = listen + t.equal(ws.onerror, listen) + }) + + t.test('onclose', (t) => { + t.plan(3) + + t.equal(ws.onclose, null) + ws.onclose = 3 + t.equal(ws.onclose, null) + ws.onclose = listen + t.equal(ws.onclose, listen) + }) + + t.test('onmessage', (t) => { + t.plan(3) + + t.equal(ws.onmessage, null) + ws.onmessage = 3 + t.equal(ws.onmessage, null) + ws.onmessage = listen + t.equal(ws.onmessage, listen) + }) +}) diff --git a/test/websocket/receive.js b/test/websocket/receive.js index ecb21be85d2..a66902202a4 100644 --- a/test/websocket/receive.js +++ b/test/websocket/receive.js @@ -28,3 +28,33 @@ test('Receiving a frame with a payload length > 2^31-1 bytes', (t) => { t.type(event.error, Error) // error event is emitted }) }) + +test('Receiving an ArrayBuffer', (t) => { + t.plan(3) + + const server = new WebSocketServer({ port: 0 }) + + server.on('connection', (ws) => { + ws.on('message', (data, isBinary) => { + ws.send(data, { binary: true }) + + ws.close(1000) + }) + }) + + t.teardown(server.close.bind(server)) + const ws = new WebSocket(`ws://localhost:${server.address().port}`) + + ws.addEventListener('open', () => { + ws.binaryType = 'what' + t.equal(ws.binaryType, 'blob') + + ws.binaryType = 'arraybuffer' // <-- + ws.send('Hello') + }) + + ws.addEventListener('message', ({ data }) => { + t.type(data, ArrayBuffer) + t.same(Buffer.from(data), Buffer.from('Hello')) + }) +}) diff --git a/test/websocket/send.js b/test/websocket/send.js index ebc5d1fb55d..4ba2a5b7dfb 100644 --- a/test/websocket/send.js +++ b/test/websocket/send.js @@ -58,6 +58,25 @@ test('Sending data after close', (t) => { ws.addEventListener('error', t.fail) }) +test('Sending data before connected', (t) => { + t.plan(2) + + const server = new WebSocketServer({ port: 0 }) + + t.teardown(server.close.bind(server)) + const ws = new WebSocket(`ws://localhost:${server.address().port}`) + + t.throws( + () => ws.send('Not sent'), + { + name: 'InvalidStateError', + constructor: DOMException + } + ) + + t.equal(ws.readyState, WebSocket.CONNECTING) +}) + test('Sending data to a server', (t) => { t.plan(3)