From 95482149a98d09c21b680453f9310e3c8f68593a Mon Sep 17 00:00:00 2001 From: Greg Kubisa Date: Tue, 17 Oct 2017 16:02:30 +0100 Subject: [PATCH 1/4] Always update connection state using _setState --- lib/client/connection.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/client/connection.js b/lib/client/connection.js index 19a332bdf..cb6ffd464 100644 --- a/lib/client/connection.js +++ b/lib/client/connection.js @@ -48,6 +48,8 @@ function Connection(socket) { this.debug = false; + this.state = 'disconnected' + this.bindToSocket(socket); } emitter.mixin(Connection); @@ -90,7 +92,7 @@ Connection.prototype.bindToSocket = function(socket) { // - 'disconnected' Connection is closed, but it will reconnect automatically // - 'closed' The connection was closed by the client, and will not reconnect // - 'stopped' The connection was closed by the server, and will not reconnect - this.state = (socket.readyState === 0 || socket.readyState === 1) ? 'connecting' : 'disconnected'; + this._setState((socket.readyState === 0 || socket.readyState === 1) ? 'connecting' : 'disconnected'); // This is a helper variable the document uses to see whether we're // currently in a 'live' state. It is true if and only if we're connected From c2a5e1317948a045f9cdffffa6cab483c1449de0 Mon Sep 17 00:00:00 2001 From: Greg Kubisa Date: Tue, 2 Jan 2018 14:53:20 +0000 Subject: [PATCH 2/4] Avoid synchronous event when creating Connection --- lib/client/connection.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/client/connection.js b/lib/client/connection.js index cb6ffd464..f8adb9513 100644 --- a/lib/client/connection.js +++ b/lib/client/connection.js @@ -5,6 +5,11 @@ var ShareDBError = require('../error'); var types = require('../types'); var util = require('../util'); +function connectionState(socket) { + if (socket.readyState === 0 || socket.readyState === 1) return 'connecting'; + return 'disconnected'; +} + /** * Handles communication with the sharejs server and provides queries and * documents. @@ -48,7 +53,7 @@ function Connection(socket) { this.debug = false; - this.state = 'disconnected' + this.state = connectionState(socket); this.bindToSocket(socket); } @@ -92,7 +97,8 @@ Connection.prototype.bindToSocket = function(socket) { // - 'disconnected' Connection is closed, but it will reconnect automatically // - 'closed' The connection was closed by the client, and will not reconnect // - 'stopped' The connection was closed by the server, and will not reconnect - this._setState((socket.readyState === 0 || socket.readyState === 1) ? 'connecting' : 'disconnected'); + var newState = connectionState(socket); + this._setState(newState); // This is a helper variable the document uses to see whether we're // currently in a 'live' state. It is true if and only if we're connected From f1e3fa2e3d81369ad355a7e4a16701564489e281 Mon Sep 17 00:00:00 2001 From: rachael Date: Tue, 19 Dec 2017 12:53:19 -0800 Subject: [PATCH 3/4] Add tests for connection state management --- test/client/connection.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/client/connection.js b/test/client/connection.js index d579573fd..b6ad730ce 100644 --- a/test/client/connection.js +++ b/test/client/connection.js @@ -90,4 +90,43 @@ describe('client connection', function() { }); }); + describe('state management using setSocket', function() { + it('initial state is connecting', function() { + var connection = this.backend.connect(); + expect(connection.state).equal('connecting'); + }); + + it('after connected event is emitted, state is connected', function(done) { + var connection = this.backend.connect(); + connection.on('connected', function() { + expect(connection.state).equal('connected'); + done(); + }); + }); + + it('when connection is manually closed, state is closed', function(done) { + var connection = this.backend.connect(); + connection.on('connected', function() { + connection.close(); + }); + connection.on('closed', function() { + expect(connection.state).equal('closed'); + done(); + }); + }); + + it('when connection is disconnected, state is disconnected', function(done) { + var connection = this.backend.connect(); + connection.on('connected', function() { + // Mock a disconnection by providing a reason + connection.socket.close('foo'); + }); + connection.on('disconnected', function() { + expect(connection.state).equal('disconnected'); + done(); + }); + }); + + }); + }); From 90043af58663d936e5b16cfa0adfbc969e833dc7 Mon Sep 17 00:00:00 2001 From: Greg Kubisa Date: Tue, 2 Jan 2018 16:22:37 +0000 Subject: [PATCH 4/4] Add some connection tests --- test/client/connection.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/client/connection.js b/test/client/connection.js index b6ad730ce..a3681c0cb 100644 --- a/test/client/connection.js +++ b/test/client/connection.js @@ -1,5 +1,6 @@ var expect = require('expect.js'); var Backend = require('../../lib/backend'); +var Connection = require('../../lib/client/connection'); describe('client connection', function() { @@ -91,6 +92,34 @@ describe('client connection', function() { }); describe('state management using setSocket', function() { + it('initial connection.state is connecting, if socket.readyState is CONNECTING', function () { + // https://html.spec.whatwg.org/multipage/web-sockets.html#dom-websocket-connecting + var socket = { readyState: 0 } + var connection = new Connection(socket) + expect(connection.state).equal('connecting'); + }); + + it('initial connection.state is connecting, if socket.readyState is OPEN', function () { + // https://html.spec.whatwg.org/multipage/web-sockets.html#dom-websocket-open + var socket = { readyState: 1 } + var connection = new Connection(socket) + expect(connection.state).equal('connecting'); + }); + + it('initial connection.state is disconnected, if socket.readyState is CLOSING', function () { + // https://html.spec.whatwg.org/multipage/web-sockets.html#dom-websocket-closing + var socket = { readyState: 2 } + var connection = new Connection(socket) + expect(connection.state).equal('disconnected'); + }); + + it('initial connection.state is disconnected, if socket.readyState is CLOSED', function () { + // https://html.spec.whatwg.org/multipage/web-sockets.html#dom-websocket-closed + var socket = { readyState: 3 } + var connection = new Connection(socket) + expect(connection.state).equal('disconnected'); + }); + it('initial state is connecting', function() { var connection = this.backend.connect(); expect(connection.state).equal('connecting');