From 7944be712fadd3d206a36ab7810254f977c352f4 Mon Sep 17 00:00:00 2001 From: moozzyk Date: Wed, 29 Mar 2017 13:07:24 -0700 Subject: [PATCH] Allow starting connection only once --- .../Connection.spec.ts | 66 +++++++++++++++++++ .../Connection.ts | 13 ++-- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS.Tests/Connection.spec.ts b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS.Tests/Connection.spec.ts index 2f5003de99..1275a92cb9 100644 --- a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS.Tests/Connection.spec.ts +++ b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS.Tests/Connection.spec.ts @@ -27,4 +27,70 @@ describe("Connection", () => { done(); } }); + + it("cannot start a running connection", async (done) => { + let options: ISignalROptions = { + httpClient: { + get(url: string): Promise { + if (url.indexOf("/negotiate") >= 0) { + connection.start() + .then(() => { + fail(); + done(); + }) + .catch((error: Error) => { + expect(error.message).toBe("Cannot start a connection that is not in the 'Initial' state."); + done(); + }); + + return Promise.reject("error"); + } + return Promise.resolve(""); + } + } + } as ISignalROptions; + + let connection = new Connection("http://tempuri.org", undefined, options); + + try { + await connection.start(); + } + catch (e) { + // This exception is thrown after the actual verification is completed. + // The connection is not setup to be running so just ignore the error. + } + }); + + it("cannot start a stopped connection", async (done) => { + let options: ISignalROptions = { + httpClient: { + get(url: string): Promise { + if (url.indexOf("/negotiate") >= 0) { + return Promise.reject("error"); + } + return Promise.resolve(""); + } + } + } as ISignalROptions; + + let connection = new Connection("http://tempuri.org", undefined, options); + + try { + // start will fail and transition the connection to the Disconnected state + await connection.start(); + } + catch (e) { + // The connection is not setup to be running so just ignore the error. + } + + try { + await connection.start(); + fail(); + done(); + } + catch (e) { + expect(e.message).toBe("Cannot start a connection that is not in the 'Initial' state."); + done(); + } + }); }); diff --git a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Connection.ts b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Connection.ts index 47397ed979..3fb7b1ef41 100644 --- a/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Connection.ts +++ b/client-ts/Microsoft.AspNetCore.SignalR.Client.TS/Connection.ts @@ -5,9 +5,10 @@ import { IHttpClient, HttpClient } from "./HttpClient" import { ISignalROptions } from "./ISignalROptions" enum ConnectionState { - Disconnected, + Initial, Connecting, - Connected + Connected, + Disconnected } export class Connection implements IConnection { @@ -22,14 +23,16 @@ export class Connection implements IConnection { this.url = url; this.queryString = queryString; this.httpClient = options.httpClient || new HttpClient(); - this.connectionState = ConnectionState.Disconnected; + this.connectionState = ConnectionState.Initial; } async start(transportName: string = "webSockets"): Promise { - if (this.connectionState != ConnectionState.Disconnected) { - throw new Error("Cannot start a connection that is not in the 'Disconnected' state"); + if (this.connectionState != ConnectionState.Initial) { + throw new Error("Cannot start a connection that is not in the 'Initial' state."); } + this.connectionState = ConnectionState.Connecting; + this.transport = this.createTransport(transportName); this.transport.onDataReceived = this.onDataReceived; this.transport.onClosed = e => this.stopConnection(e);