From 46cf13b2fc5ac30d100997d296889a7da266103b Mon Sep 17 00:00:00 2001 From: moozzyk Date: Wed, 30 Nov 2016 14:16:18 -0800 Subject: [PATCH] Hub connection tests --- .../HubConnection.ts | 8 +- .../Transports.ts | 13 ++- .../EchoEndPoint.cs | 5 +- .../Program.cs | 5 +- .../Startup.cs | 9 ++- .../TestHub.cs | 26 ++++++ .../wwwroot/connectionTests.html | 1 + .../wwwroot/js/common.js | 4 + .../wwwroot/js/connectionTests.js | 3 +- .../wwwroot/js/hubConnectionTests.js | 79 +++++++++++++++++++ .../wwwroot/js/webSocketTests.js | 2 +- 11 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 test/Microsoft.AspNetCore.SignalR.Test.Server/TestHub.cs create mode 100644 test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/hubConnectionTests.js diff --git a/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts b/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts index c0b18fca18..803481afee 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts +++ b/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts @@ -35,6 +35,10 @@ export class HubConnection { private dataReceived(data: any) { //TODO: separate JSON parsing + // Can happen if a poll request was cancelled + if (!data) { + return; + } var descriptor = JSON.parse(data); if (descriptor.Method === undefined) { let invocationResult: InvocationResultDescriptor = descriptor; @@ -62,7 +66,7 @@ export class HubConnection { return this.connection.stop(); } - invoke(methodName: string, ...args: any[]): Promise { + invoke(methodName: string, ...args: any[]): Promise { let id = this.id; this.id++; @@ -76,7 +80,7 @@ export class HubConnection { let p = new Promise((resolve, reject) => { this.callbacks[id] = (invocationResult: InvocationResultDescriptor) => { if (invocationResult.Error != null) { - reject(invocationResult.Error); + reject(new Error(invocationResult.Error)); } else { resolve(invocationResult.Result); diff --git a/src/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts b/src/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts index 5526d87992..4ea8c87f1f 100644 --- a/src/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts +++ b/src/Microsoft.AspNetCore.SignalR.Client.TS/Transports.ts @@ -12,7 +12,7 @@ export class WebSocketTransport implements ITransport { private webSocket: WebSocket; connect(url: string, queryString: string = ""): Promise { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { url = url.replace(/^http/, "ws"); let connectUrl = url + "/ws?" + queryString; @@ -53,7 +53,7 @@ export class WebSocketTransport implements ITransport { return Promise.resolve(); } - return Promise.reject("WebSocket is not in OPEN state"); + return Promise.reject("WebSocket is not in the OPEN state"); } stop(): void { @@ -81,7 +81,7 @@ export class ServerSentEventsTransport implements ITransport { this.url = url; let tmp = `${this.url}/sse?${this.queryString}`; - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { let eventSource = new EventSource(`${this.url}/sse?${this.queryString}`); try { @@ -131,15 +131,21 @@ export class LongPollingTransport implements ITransport { private url: string; private queryString: string; private pollXhr: XMLHttpRequest; + private shouldPoll: boolean; connect(url: string, queryString: string): Promise { this.url = url; this.queryString = queryString; + this.shouldPoll = true; this.poll(url + "/poll?" + this.queryString) return Promise.resolve(); } private poll(url: string): void { + if (!this.shouldPoll) { + return; + } + let thisLongPollingTransport = this; let pollXhr = new XMLHttpRequest(); @@ -188,6 +194,7 @@ export class LongPollingTransport implements ITransport { } stop(): void { + this.shouldPoll = false; if (this.pollXhr) { this.pollXhr.abort(); this.pollXhr = null; diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/EchoEndPoint.cs b/test/Microsoft.AspNetCore.SignalR.Test.Server/EchoEndPoint.cs index 7434b5a0d9..45e0feace7 100644 --- a/test/Microsoft.AspNetCore.SignalR.Test.Server/EchoEndPoint.cs +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/EchoEndPoint.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.IO.Pipelines; using System.Threading.Tasks; using Microsoft.AspNetCore.Sockets; diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/Program.cs b/test/Microsoft.AspNetCore.SignalR.Test.Server/Program.cs index e3fa956da4..86618f2329 100644 --- a/test/Microsoft.AspNetCore.SignalR.Test.Server/Program.cs +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/Program.cs @@ -1,4 +1,7 @@ -using System; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/Startup.cs b/test/Microsoft.AspNetCore.SignalR.Test.Server/Startup.cs index 67a26f6eb0..29df688410 100644 --- a/test/Microsoft.AspNetCore.SignalR.Test.Server/Startup.cs +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/Startup.cs @@ -1,4 +1,7 @@ -using Microsoft.AspNetCore.Builder; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -25,6 +28,10 @@ namespace Microsoft.AspNetCore.SignalR.Test.Server app.UseStaticFiles(); app.UseSockets(options => options.MapEndpoint("/echo")); + app.UseSignalR(routes => + { + routes.MapHub("/testhub"); + }); } } } diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/TestHub.cs b/test/Microsoft.AspNetCore.SignalR.Test.Server/TestHub.cs new file mode 100644 index 0000000000..c72de8ca9b --- /dev/null +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/TestHub.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; + +namespace Microsoft.AspNetCore.SignalR.Test.Server +{ + public class TestHub : Hub + { + public string Echo(string message) + { + return message; + } + + public void ThrowException(string message) + { + throw new InvalidOperationException(message); + } + + public Task InvokeWithString(string message) + { + return Clients.Client(Context.Connection.ConnectionId).InvokeAsync("Message", message); + } + } +} diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/connectionTests.html b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/connectionTests.html index 64c0925f71..fad27119c5 100644 --- a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/connectionTests.html +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/connectionTests.html @@ -12,6 +12,7 @@ + diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/common.js b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/common.js index c7219c1475..63c50f71ae 100644 --- a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/common.js +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/common.js @@ -3,4 +3,8 @@ const ECHOENDPOINT_URL = `http://${document.location.host}/echo`; function eachTransport(action) { let transportNames = ["webSockets", "serverSentEvents", "longPolling"]; transportNames.forEach(t => action(t)); +} + +function fail() { + it.expect(true).toBe(false); } \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/connectionTests.js b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/connectionTests.js index 6b9f352a0a..dc1e561043 100644 --- a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/connectionTests.js +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/connectionTests.js @@ -1,4 +1,3 @@ - describe('connection', () => { eachTransport(transportName => { it(`over ${transportName} can send and receive messages`, done => { @@ -23,7 +22,7 @@ describe('connection', () => { connection.send(message); }) .catch(e => { - expect(true).toBe(false); + fail(); done(); }); }); diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/hubConnectionTests.js b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/hubConnectionTests.js new file mode 100644 index 0000000000..53f52d3bbc --- /dev/null +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/hubConnectionTests.js @@ -0,0 +1,79 @@ +const TESTHUBENDPOINT_URL = `http://${document.location.host}/testhub`; + +describe('hubConnection', () => { + eachTransport(transportName => { + it(`over ${transportName} can invoke server method and receive result`, done => { + const message = "Hi"; + let hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, 'formatType=json&format=text'); + + hubConnection.start(transportName) + .then(() => { + hubConnection.invoke('Echo', message) + .then(result => { + expect(result).toBe(message); + }) + .catch(() => { + fail(); + }) + .then(() => { + hubConnection.stop(); + done(); + }) + }) + .catch(() => { + fail(); + done(); + }) + }); + + it(`over ${transportName} rethrows an exception from the server`, done => { + const errorMessage = "An error occurred."; + let hubConnection = new signalR.HubConnection(TESTHUBENDPOINT_URL, 'formatType=json&format=text'); + + hubConnection.start(transportName) + .then(() => { + hubConnection.invoke('ThrowException', errorMessage) + .then(() => { + // exception expected but none thrown + fail(); + }) + .catch(e => { + expect(e.message).toBe(errorMessage); + }) + .then(() => { + hubConnection.stop(); + done(); + }) + }) + .catch(() => { + fail(); + done(); + }) + }); + + it(`over ${transportName} can receive server calls`, done => { + let client = new signalR.HubConnection(TESTHUBENDPOINT_URL, 'formatType=json&format=text'); + const message = "Hello SignalR"; + + client.on("Message", msg => { + expect(msg).toBe(message); + client.stop(); + done(); + }); + + client.start(transportName) + .then(() => { + client.invoke('InvokeWithString', message) + .catch(e => { + fail(); + client.stop(); + done(); + }); + }) + .catch(e => { + fail(); + done(); + }) + }); + }); +}); \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/webSocketTests.js b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/webSocketTests.js index 8c6abefd84..9a0fb49132 100644 --- a/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/webSocketTests.js +++ b/test/Microsoft.AspNetCore.SignalR.Test.Server/wwwroot/js/webSocketTests.js @@ -9,7 +9,7 @@ }; webSocket.onerror = event => { - expect(true).toBe(false); + fail(); done(); };