Making the client and tests work on IE
This commit is contained in:
parent
ff2bf5ad75
commit
2a36aa141d
|
|
@ -15,7 +15,7 @@ export class Base64EncodedHubProtocol implements IHubProtocol {
|
|||
parseMessages(input: any): HubMessage[] {
|
||||
// The format of the message is `size:message;`
|
||||
let pos = input.indexOf(":");
|
||||
if (pos == -1 || !input.endsWith(";")) {
|
||||
if (pos == -1 || input[input.length - 1] != ';') {
|
||||
throw new Error("Invalid payload.");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export namespace TextMessageFormat {
|
|||
}
|
||||
|
||||
export function parse(input: string): string[] {
|
||||
if (!input.endsWith(RecordSeparator)) {
|
||||
if (input[input.length - 1] != RecordSeparator) {
|
||||
throw new Error("Message is incomplete.");
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +57,10 @@ export namespace BinaryMessageFormat {
|
|||
}
|
||||
|
||||
if (uint8Array.byteLength >= (offset + 8 + size)) {
|
||||
result.push(uint8Array.slice(offset + 8, offset + 8 + size))
|
||||
// IE does not support .slice() so use subarray
|
||||
result.push(uint8Array.slice
|
||||
? uint8Array.slice(offset + 8, offset + 8 + size)
|
||||
: uint8Array.subarray(offset + 8, offset + 8 + size));
|
||||
}
|
||||
else {
|
||||
throw new Error("Incomplete message");
|
||||
|
|
|
|||
|
|
@ -55,11 +55,10 @@ export class HubConnection {
|
|||
case MessageType.Completion:
|
||||
let callback = this.callbacks.get(message.invocationId);
|
||||
if (callback != null) {
|
||||
callback(message);
|
||||
|
||||
if (message.type == MessageType.Completion) {
|
||||
this.callbacks.delete(message.invocationId);
|
||||
}
|
||||
callback(message);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -195,9 +195,6 @@ export class LongPollingTransport implements ITransport {
|
|||
}
|
||||
|
||||
let pollXhr = new XMLHttpRequest();
|
||||
if (transferMode === TransferMode.Binary) {
|
||||
pollXhr.responseType = "arraybuffer";
|
||||
}
|
||||
|
||||
pollXhr.onload = () => {
|
||||
if (pollXhr.status == 200) {
|
||||
|
|
@ -248,6 +245,11 @@ export class LongPollingTransport implements ITransport {
|
|||
|
||||
this.pollXhr = pollXhr;
|
||||
this.pollXhr.open("GET", url, true);
|
||||
if (transferMode === TransferMode.Binary) {
|
||||
this.pollXhr.responseType = "arraybuffer";
|
||||
}
|
||||
// IE caches xhr requests
|
||||
this.pollXhr.setRequestHeader("Cache-Control", "no-cache");
|
||||
// TODO: consider making timeout configurable
|
||||
this.pollXhr.timeout = 120000;
|
||||
this.pollXhr.send();
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
<script type="text/javascript" src="lib/jasmine/jasmine.js"></script>
|
||||
<script type="text/javascript" src="lib/jasmine/jasmine-html.js"></script>
|
||||
<script type="text/javascript" src="lib/jasmine/boot.js"></script>
|
||||
<script type="text/javascript" src="lib/signalr/signalr-client.min.js"></script>
|
||||
<script type="text/javascript" src="lib/signalr/signalr-msgpackprotocol.min.js"></script>
|
||||
<script type="text/javascript" src="lib/signalr/signalr-clientES5.min.js"></script>
|
||||
<script type="text/javascript" src="lib/signalr/signalr-msgpackprotocolES5.min.js"></script>
|
||||
<script src="js/common.js"></script>
|
||||
<script src="js/webSocketTests.js"></script>
|
||||
<script src="js/connectionTests.js"></script>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
const ECHOENDPOINT_URL = `http://${document.location.host}/echo`;
|
||||
"use strict";
|
||||
|
||||
var ECHOENDPOINT_URL = "http://" + document.location.host + "/echo";
|
||||
|
||||
function getTransportTypes() {
|
||||
let transportTypes = [ signalR.TransportType.WebSockets ];
|
||||
if (typeof (EventSource) !== "undefined") {
|
||||
var transportTypes = [signalR.TransportType.WebSockets];
|
||||
if (typeof EventSource !== "undefined") {
|
||||
transportTypes.push(signalR.TransportType.ServerSentEvents);
|
||||
}
|
||||
transportTypes.push(signalR.TransportType.LongPolling);
|
||||
|
|
@ -11,14 +13,16 @@ function getTransportTypes() {
|
|||
}
|
||||
|
||||
function eachTransport(action) {
|
||||
getTransportTypes().forEach(t => action(t));
|
||||
getTransportTypes().forEach(function (t) {
|
||||
return action(t);
|
||||
});
|
||||
}
|
||||
|
||||
function eachTransportAndProtocol(action) {
|
||||
let protocols = [
|
||||
new signalR.JsonHubProtocol(),
|
||||
new signalRMsgPack.MessagePackHubProtocol()
|
||||
];
|
||||
getTransportTypes().forEach(t =>
|
||||
protocols.forEach(p => action(t, p)));
|
||||
}
|
||||
var protocols = [new signalR.JsonHubProtocol(), new signalRMsgPack.MessagePackHubProtocol()];
|
||||
getTransportTypes().forEach(function (t) {
|
||||
return protocols.forEach(function (p) {
|
||||
return action(t, p);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,61 +1,58 @@
|
|||
describe('connection', () => {
|
||||
it(`can connect to the server without specifying transport explicitly`, done => {
|
||||
const message = "Hello World!";
|
||||
let connection = new signalR.HttpConnection(ECHOENDPOINT_URL);
|
||||
"use strict";
|
||||
|
||||
let received = "";
|
||||
connection.onDataReceived = data => {
|
||||
describe('connection', function () {
|
||||
it("can connect to the server without specifying transport explicitly", function (done) {
|
||||
var message = "Hello World!";
|
||||
var connection = new signalR.HttpConnection(ECHOENDPOINT_URL);
|
||||
|
||||
var received = "";
|
||||
connection.onDataReceived = function (data) {
|
||||
received += data;
|
||||
if (data == message) {
|
||||
connection.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connection.onClosed = error => {
|
||||
connection.onClosed = function (error) {
|
||||
expect(error).toBeUndefined();
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
connection.start()
|
||||
.then(() => {
|
||||
connection.send(message);
|
||||
})
|
||||
.catch(e => {
|
||||
fail();
|
||||
done();
|
||||
});
|
||||
connection.start().then(function () {
|
||||
connection.send(message);
|
||||
}).catch(function (e) {
|
||||
fail();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
eachTransport(transportType => {
|
||||
it(`over ${signalR.TransportType[transportType]} can send and receive messages`, done => {
|
||||
const message = "Hello World!";
|
||||
let connection = new signalR.HttpConnection(ECHOENDPOINT_URL,
|
||||
{
|
||||
transport: transportType,
|
||||
logger: new signalR.ConsoleLogger(signalR.LogLevel.Information)
|
||||
});
|
||||
eachTransport(function (transportType) {
|
||||
it("over " + signalR.TransportType[transportType] + " can send and receive messages", function (done) {
|
||||
var message = "Hello World!";
|
||||
var connection = new signalR.HttpConnection(ECHOENDPOINT_URL, {
|
||||
transport: transportType,
|
||||
logger: new signalR.ConsoleLogger(signalR.LogLevel.Information)
|
||||
});
|
||||
|
||||
let received = "";
|
||||
connection.onDataReceived = data => {
|
||||
var received = "";
|
||||
connection.onDataReceived = function (data) {
|
||||
received += data;
|
||||
if (data == message) {
|
||||
connection.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
connection.onClosed = error => {
|
||||
connection.onClosed = function (error) {
|
||||
expect(error).toBeUndefined();
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
connection.start()
|
||||
.then(() => {
|
||||
connection.send(message);
|
||||
})
|
||||
.catch(e => {
|
||||
fail();
|
||||
done();
|
||||
});
|
||||
connection.start().then(function () {
|
||||
connection.send(message);
|
||||
}).catch(function (e) {
|
||||
fail();
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,194 +1,149 @@
|
|||
const TESTHUBENDPOINT_URL = `http://${document.location.host}/testhub`;
|
||||
'use strict';
|
||||
|
||||
describe('hubConnection', () => {
|
||||
eachTransportAndProtocol((transportType, protocol) => {
|
||||
describe(`${protocol.name} over ${signalR.TransportType[transportType]} transport`, () => {
|
||||
it(`can invoke server method and receive result`, done => {
|
||||
const message = "你好,世界!";
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
hubConnection.onClosed = error => {
|
||||
var TESTHUBENDPOINT_URL = 'http://' + document.location.host + '/testhub';
|
||||
|
||||
describe('hubConnection', function () {
|
||||
eachTransportAndProtocol(function (transportType, protocol) {
|
||||
describe(protocol.name + ' over ' + signalR.TransportType[transportType] + ' transport', function () {
|
||||
|
||||
it('can invoke server method and receive result', function (done) {
|
||||
var message = "你好,世界!";
|
||||
var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType, logger: logger }), logger, protocol);
|
||||
hubConnection.onClosed = function (error) {
|
||||
expect(error).toBe(undefined);
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
hubConnection.start()
|
||||
.then(() => {
|
||||
hubConnection.invoke('Echo', message)
|
||||
.then(result => {
|
||||
expect(result).toBe(message);
|
||||
})
|
||||
.catch(e => {
|
||||
fail(e);
|
||||
})
|
||||
.then(() => {
|
||||
hubConnection.stop();
|
||||
})
|
||||
})
|
||||
.catch(e => {
|
||||
hubConnection.start().then(function () {
|
||||
hubConnection.invoke('Echo', message).then(function (result) {
|
||||
expect(result).toBe(message);
|
||||
}).catch(function (e) {
|
||||
fail(e);
|
||||
done();
|
||||
}).then(function () {
|
||||
hubConnection.stop();
|
||||
});
|
||||
}).catch(function (e) {
|
||||
fail(e);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(`can stream server method and receive result`, done => {
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
it('can stream server method and receive result', function (done) {
|
||||
var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType, logger: logger }), logger, protocol);
|
||||
|
||||
hubConnection.onClosed = error => {
|
||||
hubConnection.onClosed = function (error) {
|
||||
expect(error).toBe(undefined);
|
||||
done();
|
||||
}
|
||||
};
|
||||
|
||||
let received = [];
|
||||
hubConnection.start()
|
||||
.then(() => {
|
||||
hubConnection.stream('Stream')
|
||||
.subscribe({
|
||||
next: (item) => {
|
||||
received.push(item);
|
||||
},
|
||||
error: (err) => {
|
||||
fail(err);
|
||||
hubConnection.stop();
|
||||
},
|
||||
complete: () => {
|
||||
expect(received).toEqual(["a", "b", "c"]);
|
||||
hubConnection.stop();
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
fail(e);
|
||||
done();
|
||||
var received = [];
|
||||
hubConnection.start().then(function () {
|
||||
hubConnection.stream('Stream').subscribe({
|
||||
next: function next(item) {
|
||||
received.push(item);
|
||||
},
|
||||
error: function error(err) {
|
||||
fail(err);
|
||||
hubConnection.stop();
|
||||
},
|
||||
complete: function complete() {
|
||||
expect(received).toEqual(["a", "b", "c"]);
|
||||
hubConnection.stop();
|
||||
}
|
||||
});
|
||||
}).catch(function (e) {
|
||||
fail(e);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(`rethrows an exception from the server when invoking`, done => {
|
||||
const errorMessage = "An error occurred.";
|
||||
it('rethrows an exception from the server when invoking', function (done) {
|
||||
var errorMessage = "An error occurred.";
|
||||
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType, logger: logger }), logger, protocol);
|
||||
|
||||
hubConnection.start()
|
||||
.then(() => {
|
||||
hubConnection.invoke('ThrowException', errorMessage)
|
||||
.then(() => {
|
||||
// exception expected but none thrown
|
||||
fail();
|
||||
})
|
||||
.catch(e => {
|
||||
expect(e.message).toBe(errorMessage);
|
||||
})
|
||||
.then(() => {
|
||||
return hubConnection.stop();
|
||||
})
|
||||
.then(() => {
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch(e => {
|
||||
fail(e);
|
||||
hubConnection.start().then(function () {
|
||||
hubConnection.invoke('ThrowException', errorMessage).then(function () {
|
||||
// exception expected but none thrown
|
||||
fail();
|
||||
}).catch(function (e) {
|
||||
expect(e.message).toBe(errorMessage);
|
||||
}).then(function () {
|
||||
return hubConnection.stop();
|
||||
}).then(function () {
|
||||
done();
|
||||
});
|
||||
}).catch(function (e) {
|
||||
fail(e);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(`rethrows an exception from the server when streaming`, done => {
|
||||
const errorMessage = "An error occurred.";
|
||||
it('rethrows an exception from the server when streaming', function (done) {
|
||||
var errorMessage = "An error occurred.";
|
||||
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType, logger: logger }), logger, protocol);
|
||||
|
||||
hubConnection.start()
|
||||
.then(() => {
|
||||
hubConnection.stream('ThrowException', errorMessage)
|
||||
.subscribe({
|
||||
next: (item) => {
|
||||
fail();
|
||||
},
|
||||
error: (err) => {
|
||||
expect(err.message).toEqual("An error occurred.");
|
||||
done();
|
||||
},
|
||||
complete: () => {
|
||||
fail();
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
.catch(e => {
|
||||
fail(e);
|
||||
done();
|
||||
hubConnection.start().then(function () {
|
||||
hubConnection.stream('ThrowException', errorMessage).subscribe({
|
||||
next: function next(item) {
|
||||
fail();
|
||||
},
|
||||
error: function error(err) {
|
||||
expect(err.message).toEqual("An error occurred.");
|
||||
done();
|
||||
},
|
||||
complete: function complete() {
|
||||
fail();
|
||||
}
|
||||
});
|
||||
}).catch(function (e) {
|
||||
fail(e);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(`can receive server calls`, done => {
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
TESTHUBENDPOINT_URL,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
it('can receive server calls', function (done) {
|
||||
var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection(TESTHUBENDPOINT_URL, { transport: transportType, logger: logger }), logger, protocol);
|
||||
|
||||
const message = "你好 SignalR!";
|
||||
var message = "你好 SignalR!";
|
||||
|
||||
let callbackPromise = new Promise((resolve, reject) => {
|
||||
hubConnection.on("Message", msg => {
|
||||
expect(msg).toBe(message);
|
||||
resolve();
|
||||
});
|
||||
hubConnection.on("Message", function (msg) {
|
||||
expect(msg).toBe(message);
|
||||
done();
|
||||
});
|
||||
|
||||
hubConnection.start()
|
||||
.then(() => {
|
||||
return Promise.all([hubConnection.invoke('InvokeWithString', message), callbackPromise]);
|
||||
})
|
||||
.then(() => {
|
||||
return stop();
|
||||
})
|
||||
.then(() => {
|
||||
done();
|
||||
})
|
||||
.catch(e => {
|
||||
fail(e);
|
||||
done();
|
||||
});
|
||||
hubConnection.start().then(function () {
|
||||
return hubConnection.invoke('InvokeWithString', message);
|
||||
})
|
||||
.then(function() {
|
||||
return hubConnection.stop();
|
||||
})
|
||||
.catch(function (e) {
|
||||
fail(e);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(`closed with error if hub cannot be created`, done => {
|
||||
let errorRegex = {
|
||||
WebSockets: "1011", // Message is browser specific (e.g. 'Websocket closed with status code: 1011')
|
||||
it('closed with error if hub cannot be created', function (done) {
|
||||
var errorRegex = {
|
||||
WebSockets: "1011|1005", // Message is browser specific (e.g. 'Websocket closed with status code: 1011'), Edge and IE report 1005 even though the server sent 1011
|
||||
LongPolling: "Internal Server Error",
|
||||
ServerSentEvents: "Error occurred"
|
||||
};
|
||||
|
||||
let logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
let hubConnection = new signalR.HubConnection(new signalR.HttpConnection(
|
||||
`http://${document.location.host}/uncreatable`,
|
||||
{ transport: transportType, logger: logger }),
|
||||
logger,
|
||||
protocol);
|
||||
var logger = new signalR.ConsoleLogger(signalR.LogLevel.Information);
|
||||
var hubConnection = new signalR.HubConnection(new signalR.HttpConnection('http://' + document.location.host + '/uncreatable', { transport: transportType, logger: logger }), logger, protocol);
|
||||
|
||||
hubConnection.onClosed = error => {
|
||||
hubConnection.onClosed = function (error) {
|
||||
expect(error.message).toMatch(errorRegex[signalR.TransportType[transportType]]);
|
||||
done();
|
||||
}
|
||||
};
|
||||
hubConnection.start();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,22 +1,24 @@
|
|||
'use strict';
|
||||
|
||||
describe('WebSockets', function () {
|
||||
it('can be used to connect to SignalR', done => {
|
||||
const message = "message";
|
||||
it('can be used to connect to SignalR', function (done) {
|
||||
var message = "message";
|
||||
|
||||
let webSocket = new WebSocket(ECHOENDPOINT_URL.replace(/^http/, "ws"));
|
||||
var webSocket = new WebSocket(ECHOENDPOINT_URL.replace(/^http/, "ws"));
|
||||
|
||||
webSocket.onopen = () => {
|
||||
webSocket.onopen = function () {
|
||||
webSocket.send(message);
|
||||
};
|
||||
|
||||
var received = "";
|
||||
webSocket.onmessage = event => {
|
||||
webSocket.onmessage = function (event) {
|
||||
received += event.data;
|
||||
if (received === message) {
|
||||
webSocket.close();
|
||||
}
|
||||
};
|
||||
|
||||
webSocket.onclose = event => {
|
||||
webSocket.onclose = function (event) {
|
||||
if (!event.wasClean) {
|
||||
fail("connection closed with unexpected status code: " + event.code + " " + event.reason);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue