Make HttpTransportType a flags enum in TypeScript (#2179)

This commit is contained in:
Andrew Stanton-Nurse 2018-05-04 09:05:29 -07:00 committed by GitHub
parent 4c1c494748
commit c009e15b0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 66 additions and 2 deletions

View File

@ -254,6 +254,66 @@ describe("HttpConnection", () => {
expect(e.message).toBe("Unable to initialize any of the available transports.");
}
});
for (const [val, name] of [[null, "null"], [undefined, "undefined"], [0, "0"]]) {
it(`can be started using ${HttpTransportType[requestedTransport]} transport when transport mask is ${name}`, async () => {
const negotiateResponse = {
availableTransports: [
{ transport: "WebSockets", transferFormats: [ "Text", "Binary" ] },
{ transport: "ServerSentEvents", transferFormats: [ "Text" ] },
{ transport: "LongPolling", transferFormats: [ "Text", "Binary" ] },
],
connectionId: "abc123",
};
const options: IHttpConnectionOptions = {
...commonOptions,
httpClient: new TestHttpClient()
.on("POST", (r) => negotiateResponse)
.on("GET", (r) => new HttpResponse(204)),
transport: val,
} as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options);
await connection.start(TransferFormat.Text);
});
}
it(`cannot be started if server's only transport (${HttpTransportType[requestedTransport]}) is masked out by the transport option`, async() => {
const negotiateResponse = {
availableTransports: [
{ transport: "WebSockets", transferFormats: [ "Text", "Binary" ] },
{ transport: "ServerSentEvents", transferFormats: [ "Text" ] },
{ transport: "LongPolling", transferFormats: [ "Text", "Binary" ] },
],
connectionId: "abc123",
};
// Build the mask by inverting the requested transport
const transportMask = ~requestedTransport;
// Remove all transports other than the requested one
negotiateResponse.availableTransports = negotiateResponse.availableTransports
.filter((r) => r.transport === HttpTransportType[requestedTransport]);
const options: IHttpConnectionOptions = {
...commonOptions,
httpClient: new TestHttpClient()
.on("POST", (r) => negotiateResponse)
.on("GET", (r) => new HttpResponse(204)),
transport: transportMask,
} as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options);
try {
await connection.start(TransferFormat.Text);
fail("Expected connection.start to throw!");
} catch (e) {
expect(e.message).toBe("Unable to initialize any of the available transports.");
}
});
});
it("cannot be started if no transport available on server and no transport requested", async (done) => {

View File

@ -262,7 +262,7 @@ export class HttpConnection implements IConnection {
this.logger.log(LogLevel.Debug, `Skipping transport '${endpoint.transport}' because it is not supported by this client.`);
} else {
const transferFormats = endpoint.transferFormats.map((s) => TransferFormat[s]);
if (!requestedTransport || transport === requestedTransport) {
if (transportMatches(requestedTransport, transport)) {
if (transferFormats.indexOf(requestedTransferFormat) >= 0) {
if ((transport === HttpTransportType.WebSockets && typeof WebSocket === "undefined") ||
(transport === HttpTransportType.ServerSentEvents && typeof EventSource === "undefined")) {
@ -282,7 +282,7 @@ export class HttpConnection implements IConnection {
}
private isITransport(transport: any): transport is ITransport {
return typeof (transport) === "object" && "connect" in transport;
return transport && typeof (transport) === "object" && "connect" in transport;
}
private changeState(from: ConnectionState, to: ConnectionState): boolean {
@ -345,3 +345,7 @@ export class HttpConnection implements IConnection {
return negotiateUrl;
}
}
function transportMatches(requestedTransport: HttpTransportType, actualTransport: HttpTransportType) {
return !requestedTransport || ((actualTransport & requestedTransport) !== 0);
}