diff --git a/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts b/src/Microsoft.AspNetCore.SignalR.Client.TS/HubConnection.ts index c0b18fca1814ae92d34813fb66efb91c96fcbcb3..803481afee2764abe0e4a02bf1ac74b1c8f9f3b6 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<void> { + invoke(methodName: string, ...args: any[]): Promise<any> { let id = this.id; this.id++; @@ -76,7 +80,7 @@ export class HubConnection { let p = new Promise<any>((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 5526d879922a0876c1cbf19a88a3556c600c0357..4ea8c87f1f681c07490e46c9983098c605e15b2e 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<void> { - return new Promise((resolve, reject) => { + return new Promise<void>((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<void>((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<void> { 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 7434b5a0d9ab549cc8582d8dc97cd1c38250221d..45e0feace748bac2e60466af632603907dc95ebf 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 e3fa956da4c46b0e34d6a54b8a0271f7873c2419..86618f2329af880988e99677b64693e148d96059 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 67a26f6eb016976095c862c8e4b41b5be6da7179..29df68841069a2a73221000a4b351584f0976510 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<EchoEndPoint>("/echo")); + app.UseSignalR(routes => + { + routes.MapHub<TestHub>("/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 0000000000000000000000000000000000000000..c72de8ca9b79604d9821c13fc5e2aeb1fc32961e --- /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 64c0925f71e4a087283d0517de69bdc2c09ec29a..fad27119c56853b69d34eac3f31f769fe2a8210a 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 @@ <script src="js/common.js"></script> <script src="js/webSocketTests.js"></script> <script src="js/connectionTests.js"></script> + <script src="js/hubConnectionTests.js"></script> </head> <body> </body> 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 c7219c147505a18c566937d8a405d88dfad8163c..63c50f71ae6b23e3356ee92dbdc3340461324584 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 6b9f352a0a08a3168fcf8083adab6ccdf5f33674..dc1e56104317f0ae2e7a9f6e9dd37daefd3b1af1 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 0000000000000000000000000000000000000000..53f52d3bbc2cc92cded614dcd98d9348db106c46 --- /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 8c6abefd84e5e3cf0c26a13cb14e47dc2df6ef95..9a0fb49132a35ab12d10ff5ed8dcf50c49ad4213 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(); };