Skip to content

Commit

Permalink
Fix #242 (#362)
Browse files Browse the repository at this point in the history
* Fix #242

* Changes after code review
  • Loading branch information
ritave authored Jun 7, 2022
1 parent 42dc847 commit 78632a1
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 9 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"no-param-reassign": 0,
"comma-dangle": ["error", "never"],
"arrow-parens": 0,
"import/no-extraneous-dependencies": 0 // all deps are resolved with "node-resolve"
"import/no-extraneous-dependencies": 0, // all deps are resolved with "node-resolve"
"no-underscore-dangle": ["error", { "allowAfterThis": true }]
}
}
25 changes: 17 additions & 8 deletions src/websocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ class WebSocket extends EventTarget {
constructor(url, protocols) {
super();

this._onopen = null;
this._onmessage = null;
this._onerror = null;
this._onclose = null;

this.url = urlVerification(url);
protocols = protocolVerification(protocols);
this.protocol = protocols[0] || '';
Expand Down Expand Up @@ -94,38 +99,42 @@ class WebSocket extends EventTarget {
}

get onopen() {
return this.listeners.open;
return this._onopen;
}

get onmessage() {
return this.listeners.message;
return this._onmessage;
}

get onclose() {
return this.listeners.close;
return this._onclose;
}

get onerror() {
return this.listeners.error;
return this._onerror;
}

set onopen(listener) {
delete this.listeners.open;
this.removeEventListener('open', this._onopen);
this._onopen = listener;
this.addEventListener('open', listener);
}

set onmessage(listener) {
delete this.listeners.message;
this.removeEventListener('message', this._onmessage);
this._onmessage = listener;
this.addEventListener('message', listener);
}

set onclose(listener) {
delete this.listeners.close;
this.removeEventListener('close', this._onclose);
this._onclose = listener;
this.addEventListener('close', listener);
}

set onerror(listener) {
delete this.listeners.error;
this.removeEventListener('error', this._onerror);
this._onerror = listener;
this.addEventListener('error', listener);
}

Expand Down
90 changes: 90 additions & 0 deletions tests/issues/242.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import test from 'ava';
import Server from '../../src/server';
import WebSocket from '../../src/websocket';
import Event from '../../src/event/event';

test('websocket on* methods family returns a single listener', t => {
const socketUrl = 'ws://localhost:8080';
const mockServer = new Server(socketUrl);
const mockSocket = new WebSocket(socketUrl);

const listener = () => {
/* do nothing */
};

mockSocket.onopen = listener;
mockSocket.onmessage = listener;
mockSocket.onerror = listener;
mockSocket.onclose = listener;

t.is(mockSocket.onopen, listener);
t.is(mockSocket.onmessage, listener);
t.is(mockSocket.onerror, listener);
t.is(mockSocket.onclose, listener);

mockServer.close();
});

test("websocket on* methods family doesn't delete other listeners", async t => {
const socketUrl = 'ws://localhost:8080';
const mockServer = new Server(socketUrl);
const mockSocket = new WebSocket(socketUrl);

mockServer.on('connection', socket => {
socket.send('test message');
});

let onOpenCalled = 0;
let onMessageCalled = 0;
let onErrorCalled = 0;

let onCloseEventResolve;
let onCloseResolve;
const allClosed = Promise.all([
new Promise(r => {
onCloseEventResolve = r;
}),
new Promise(r => {
onCloseResolve = r;
})
]);

mockSocket.addEventListener('open', () => {
onOpenCalled += 1;
});
mockSocket.addEventListener('message', () => {
onMessageCalled += 1;
mockSocket.dispatchEvent(new Event('error'));
});
mockSocket.addEventListener('error', () => {
onErrorCalled += 1;
mockSocket.close();
});
mockSocket.addEventListener('close', () => onCloseEventResolve());

const throwCb = () => {
throw new Error('this call should have been replaced');
};
mockSocket.onopen = throwCb;
mockSocket.onopen = () => {
onOpenCalled += 1;
};
mockSocket.onmessage = throwCb;
mockSocket.onmessage = () => {
onMessageCalled += 1;
};
mockSocket.onerror = throwCb;
mockSocket.onerror = () => {
onErrorCalled += 1;
};
mockSocket.onclose = throwCb;
mockSocket.onclose = () => onCloseResolve();

await allClosed;

t.is(onOpenCalled, 2);
t.is(onMessageCalled, 2);
t.is(onErrorCalled, 2);

mockServer.close();
});

0 comments on commit 78632a1

Please sign in to comment.