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();
         };