fix #2407 by tslinting tests before running (#2459)

This commit is contained in:
Andrew Stanton-Nurse 2018-06-11 14:19:33 -07:00 committed by GitHub
parent c7ebae47ea
commit 7317762b29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 164 additions and 161 deletions

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { HttpTransportType, IHttpConnectionOptions, LogLevel, TransferFormat } from "@aspnet/signalr"; import { HttpTransportType, IHttpConnectionOptions, TransferFormat } from "@aspnet/signalr";
import { eachTransport, ECHOENDPOINT_URL } from "./Common"; import { eachTransport, ECHOENDPOINT_URL } from "./Common";
import { TestLogger } from "./TestLogger"; import { TestLogger } from "./TestLogger";
@ -23,9 +23,7 @@ describe("connection", () => {
...commonOptions, ...commonOptions,
}); });
let received = "";
connection.onreceive = (data) => { connection.onreceive = (data) => {
received += data;
if (data === message) { if (data === message) {
connection.stop(); connection.stop();
} }
@ -55,9 +53,7 @@ describe("connection", () => {
transport: transportType, transport: transportType,
}); });
let received = "";
connection.onreceive = (data) => { connection.onreceive = (data) => {
received += data;
if (data === message) { if (data === message) {
connection.stop(); connection.stop();
} }

View File

@ -1,7 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
import { AbortError, DefaultHttpClient, HttpClient, HttpRequest, HttpResponse, HttpTransportType, HubConnection, HubConnectionBuilder, IHttpConnectionOptions, IStreamSubscriber, JsonHubProtocol, LogLevel } from "@aspnet/signalr"; import { AbortError, DefaultHttpClient, HttpClient, HttpRequest, HttpResponse, HttpTransportType, HubConnectionBuilder, IHttpConnectionOptions, JsonHubProtocol } from "@aspnet/signalr";
import { MessagePackHubProtocol } from "@aspnet/signalr-protocol-msgpack"; import { MessagePackHubProtocol } from "@aspnet/signalr-protocol-msgpack";
import { eachTransport, eachTransportAndProtocol, ENDPOINT_BASE_URL } from "./Common"; import { eachTransport, eachTransportAndProtocol, ENDPOINT_BASE_URL } from "./Common";

View File

@ -5,6 +5,7 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "cd ./signalr && npm run build && cd ../signalr-protocol-msgpack && npm run build", "build": "cd ./signalr && npm run build && cd ../signalr-protocol-msgpack && npm run build",
"pretest": "tslint -c ./tslint.json -p ./signalr/tests/tsconfig.json && tslint -c ./tslint.json -p ./signalr-protocol-msgpack/tests/tsconfig.json",
"test": "jest", "test": "jest",
"coverage": "jest --coverage" "coverage": "jest --coverage"
}, },

View File

@ -7,7 +7,6 @@ import { IHttpConnectionOptions } from "./IHttpConnectionOptions";
import { ILogger, LogLevel } from "./ILogger"; import { ILogger, LogLevel } from "./ILogger";
import { HttpTransportType, ITransport, TransferFormat } from "./ITransport"; import { HttpTransportType, ITransport, TransferFormat } from "./ITransport";
import { LongPollingTransport } from "./LongPollingTransport"; import { LongPollingTransport } from "./LongPollingTransport";
import { EventSourceConstructor, WebSocketConstructor } from "./Polyfills";
import { ServerSentEventsTransport } from "./ServerSentEventsTransport"; import { ServerSentEventsTransport } from "./ServerSentEventsTransport";
import { Arg, createLogger } from "./Utils"; import { Arg, createLogger } from "./Utils";
import { WebSocketTransport } from "./WebSocketTransport"; import { WebSocketTransport } from "./WebSocketTransport";

View File

@ -6,7 +6,6 @@ import { IConnection } from "./IConnection";
import { CancelInvocationMessage, CompletionMessage, IHubProtocol, InvocationMessage, MessageType, StreamInvocationMessage, StreamItemMessage } from "./IHubProtocol"; import { CancelInvocationMessage, CompletionMessage, IHubProtocol, InvocationMessage, MessageType, StreamInvocationMessage, StreamItemMessage } from "./IHubProtocol";
import { ILogger, LogLevel } from "./ILogger"; import { ILogger, LogLevel } from "./ILogger";
import { IStreamResult } from "./Stream"; import { IStreamResult } from "./Stream";
import { TextMessageFormat } from "./TextMessageFormat";
import { Arg, Subject } from "./Utils"; import { Arg, Subject } from "./Utils";
const DEFAULT_TIMEOUT_IN_MS: number = 30 * 1000; const DEFAULT_TIMEOUT_IN_MS: number = 30 * 1000;
@ -354,7 +353,11 @@ export class HubConnection {
break; break;
case MessageType.Close: case MessageType.Close:
this.logger.log(LogLevel.Information, "Close message received from server."); this.logger.log(LogLevel.Information, "Close message received from server.");
// We don't want to wait on the stop itself.
// tslint:disable-next-line:no-floating-promises
this.connection.stop(message.error ? new Error("Server returned an error on close: " + message.error) : undefined); this.connection.stop(message.error ? new Error("Server returned an error on close: " + message.error) : undefined);
break; break;
default: default:
this.logger.log(LogLevel.Warning, "Invalid message type: " + message.type); this.logger.log(LogLevel.Warning, "Invalid message type: " + message.type);
@ -377,12 +380,18 @@ export class HubConnection {
this.logger.log(LogLevel.Error, message); this.logger.log(LogLevel.Error, message);
const error = new Error(message); const error = new Error(message);
// We don't want to wait on the stop itself.
// tslint:disable-next-line:no-floating-promises
this.connection.stop(error); this.connection.stop(error);
throw error; throw error;
} }
if (responseMessage.error) { if (responseMessage.error) {
const message = "Server returned handshake error: " + responseMessage.error; const message = "Server returned handshake error: " + responseMessage.error;
this.logger.log(LogLevel.Error, message); this.logger.log(LogLevel.Error, message);
// We don't want to wait on the stop itself.
// tslint:disable-next-line:no-floating-promises
this.connection.stop(new Error(message)); this.connection.stop(new Error(message));
} else { } else {
this.logger.log(LogLevel.Debug, "Server handshake complete."); this.logger.log(LogLevel.Debug, "Server handshake complete.");
@ -405,7 +414,8 @@ export class HubConnection {
private serverTimeout() { private serverTimeout() {
// The server hasn't talked to us in a while. It doesn't like us anymore ... :( // The server hasn't talked to us in a while. It doesn't like us anymore ... :(
// Terminate the connection // Terminate the connection, but we don't need to wait on the promise.
// tslint:disable-next-line:no-floating-promises
this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server.")); this.connection.stop(new Error("Server timeout elapsed without receiving a message from the server."));
} }
@ -417,6 +427,9 @@ export class HubConnection {
// This is not supported in v1. So we return an error to avoid blocking the server waiting for the response. // This is not supported in v1. So we return an error to avoid blocking the server waiting for the response.
const message = "Server requested a response, which is not supported in this version of the client."; const message = "Server requested a response, which is not supported in this version of the client.";
this.logger.log(LogLevel.Error, message); this.logger.log(LogLevel.Error, message);
// We don't need to wait on this Promise.
// tslint:disable-next-line:no-floating-promises
this.connection.stop(new Error(message)); this.connection.stop(new Error(message));
} }
} else { } else {

View File

@ -17,7 +17,6 @@ export class LongPollingTransport implements ITransport {
private readonly pollAbort: AbortController; private readonly pollAbort: AbortController;
private url?: string; private url?: string;
private pollXhr?: XMLHttpRequest;
private running: boolean; private running: boolean;
private receiving?: Promise<void>; private receiving?: Promise<void>;
private closeError?: Error; private closeError?: Error;

View File

@ -45,6 +45,8 @@ export interface IStreamResult<T> {
* *
* @typeparam T The type of the items being sent by the server. * @typeparam T The type of the items being sent by the server.
*/ */
// We can't remove this, it's a breaking change, but it's not used.
// tslint:disable-next-line:no-unused-variable
export interface ISubscription<T> { export interface ISubscription<T> {
/** Disconnects the {@link IStreamSubscriber} associated with this subscription from the stream. */ /** Disconnects the {@link IStreamSubscriber} associated with this subscription from the stream. */
dispose(): void; dispose(): void;

View File

@ -7,15 +7,15 @@ import { IHttpConnectionOptions } from "../src/IHttpConnectionOptions";
import { HttpTransportType, ITransport, TransferFormat } from "../src/ITransport"; import { HttpTransportType, ITransport, TransferFormat } from "../src/ITransport";
import { HttpError } from "../src/Errors"; import { HttpError } from "../src/Errors";
import { LogLevel } from "../src/ILogger"; import { NullLogger } from "../src/Loggers";
import { EventSourceConstructor, WebSocketConstructor } from "../src/Polyfills"; import { EventSourceConstructor } from "../src/Polyfills";
import { TextMessageFormat } from "../src/TextMessageFormat";
import { WebSocketTransport } from "../src/WebSocketTransport";
import { eachEndpointUrl, eachTransport } from "./Common"; import { eachEndpointUrl, eachTransport } from "./Common";
import { TestHttpClient } from "./TestHttpClient"; import { TestHttpClient } from "./TestHttpClient";
import { PromiseSource } from "./Utils"; import { PromiseSource } from "./Utils";
const commonOptions: IHttpConnectionOptions = { const commonOptions: IHttpConnectionOptions = {
logger: NullLogger.instance,
}; };
const defaultConnectionId = "abc123"; const defaultConnectionId = "abc123";
@ -45,13 +45,13 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => Promise.reject("error")) .on("POST", () => Promise.reject("error"))
.on("GET", (r) => ""), .on("GET", () => ""),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options); const connection = new HttpConnection("http://tempuri.org", options);
expect(connection.start(TransferFormat.Text)) await expect(connection.start(TransferFormat.Text))
.rejects .rejects
.toThrow("error"); .toThrow("error");
}); });
@ -61,15 +61,15 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => { .on("POST", () => {
negotiating.resolve(); negotiating.resolve();
return defaultNegotiateResponse; return defaultNegotiateResponse;
}), }),
transport: { transport: {
connect(url: string, transferFormat: TransferFormat) { connect() {
return Promise.resolve(); return Promise.resolve();
}, },
send(data: any) { send() {
return Promise.resolve(); return Promise.resolve();
}, },
stop() { stop() {
@ -93,15 +93,13 @@ describe("HttpConnection", () => {
}); });
it("can start a stopped connection", async () => { it("can start a stopped connection", async () => {
let negotiateCalls = 0;
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => { .on("POST", () => {
negotiateCalls += 1;
return Promise.reject("reached negotiate"); return Promise.reject("reached negotiate");
}) })
.on("GET", (r) => ""), .on("GET", () => ""),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options); const connection = new HttpConnection("http://tempuri.org", options);
@ -119,12 +117,12 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => { .on("POST", async () => {
connection.stop(); await connection.stop();
return "{}"; return "{}";
}) })
.on("GET", (r) => { .on("GET", async () => {
connection.stop(); await connection.stop();
return ""; return "";
}), }),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
@ -143,8 +141,8 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => ({ connectionId: "42", availableTransports: [] })) .on("POST", () => ({ connectionId: "42", availableTransports: [] }))
.on("GET", (r) => { throw new Error("fail"); }), .on("GET", () => { throw new Error("fail"); }),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org?q=myData", options); const connection = new HttpConnection("http://tempuri.org?q=myData", options);
@ -161,7 +159,7 @@ describe("HttpConnection", () => {
connectUrl.resolve(url); connectUrl.resolve(url);
return Promise.resolve(); return Promise.resolve();
}, },
send(data: any): Promise<void> { send(): Promise<void> {
return Promise.resolve(); return Promise.resolve();
}, },
stop(): Promise<void> { stop(): Promise<void> {
@ -174,8 +172,8 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => "{ \"connectionId\": \"42\" }") .on("POST", () => "{ \"connectionId\": \"42\" }")
.on("GET", (r) => ""), .on("GET", () => ""),
transport: fakeTransport, transport: fakeTransport,
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
@ -201,10 +199,10 @@ describe("HttpConnection", () => {
negotiateUrl.resolve(r.url); negotiateUrl.resolve(r.url);
throw new HttpError("We don't care how this turns out", 500); throw new HttpError("We don't care how this turns out", 500);
}) })
.on("GET", (r) => { .on("GET", () => {
return new HttpResponse(204); return new HttpResponse(204);
}) })
.on("DELETE", (r) => new HttpResponse(202)), .on("DELETE", () => new HttpResponse(202)),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection(givenUrl, options); const connection = new HttpConnection(givenUrl, options);
@ -232,8 +230,8 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => negotiateResponse) .on("POST", () => negotiateResponse)
.on("GET", (r) => new HttpResponse(204)), .on("GET", () => new HttpResponse(204)),
transport: requestedTransport, transport: requestedTransport,
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
@ -248,9 +246,9 @@ describe("HttpConnection", () => {
it(`can be started using ${HttpTransportType[requestedTransport]} transport when transport mask is ${name}`, async () => { it(`can be started using ${HttpTransportType[requestedTransport]} transport when transport mask is ${name}`, async () => {
const negotiateResponse = { const negotiateResponse = {
availableTransports: [ availableTransports: [
{ transport: "WebSockets", transferFormats: [ "Text", "Binary" ] }, { transport: "WebSockets", transferFormats: ["Text", "Binary"] },
{ transport: "ServerSentEvents", transferFormats: [ "Text" ] }, { transport: "ServerSentEvents", transferFormats: ["Text"] },
{ transport: "LongPolling", transferFormats: [ "Text", "Binary" ] }, { transport: "LongPolling", transferFormats: ["Text", "Binary"] },
], ],
connectionId: "abc123", connectionId: "abc123",
}; };
@ -258,8 +256,8 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => negotiateResponse) .on("POST", () => negotiateResponse)
.on("GET", (r) => new HttpResponse(204)), .on("GET", () => new HttpResponse(204)),
transport: val, transport: val,
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
@ -272,9 +270,9 @@ describe("HttpConnection", () => {
it(`cannot be started if server's only transport (${HttpTransportType[requestedTransport]}) is masked out by the transport option`, async () => { it(`cannot be started if server's only transport (${HttpTransportType[requestedTransport]}) is masked out by the transport option`, async () => {
const negotiateResponse = { const negotiateResponse = {
availableTransports: [ availableTransports: [
{ transport: "WebSockets", transferFormats: [ "Text", "Binary" ] }, { transport: "WebSockets", transferFormats: ["Text", "Binary"] },
{ transport: "ServerSentEvents", transferFormats: [ "Text" ] }, { transport: "ServerSentEvents", transferFormats: ["Text"] },
{ transport: "LongPolling", transferFormats: [ "Text", "Binary" ] }, { transport: "LongPolling", transferFormats: ["Text", "Binary"] },
], ],
connectionId: "abc123", connectionId: "abc123",
}; };
@ -289,8 +287,8 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => negotiateResponse) .on("POST", () => negotiateResponse)
.on("GET", (r) => new HttpResponse(204)), .on("GET", () => new HttpResponse(204)),
transport: transportMask, transport: transportMask,
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
@ -309,8 +307,8 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => ({ connectionId: "42", availableTransports: [] })) .on("POST", () => ({ connectionId: "42", availableTransports: [] }))
.on("GET", (r) => ""), .on("GET", () => ""),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options); const connection = new HttpConnection("http://tempuri.org", options);
@ -351,7 +349,7 @@ describe("HttpConnection", () => {
let firstNegotiate = true; let firstNegotiate = true;
let firstPoll = true; let firstPoll = true;
const httpClient = new TestHttpClient() const httpClient = new TestHttpClient()
.on("POST", /negotiate$/, (r) => { .on("POST", /negotiate$/, () => {
if (firstNegotiate) { if (firstNegotiate) {
firstNegotiate = false; firstNegotiate = false;
return { url: "https://another.domain.url/chat" }; return { url: "https://another.domain.url/chat" };
@ -361,14 +359,14 @@ describe("HttpConnection", () => {
connectionId: "0rge0d00-0040-0030-0r00-000q00r00e00", connectionId: "0rge0d00-0040-0030-0r00-000q00r00e00",
}; };
}) })
.on("GET", (r) => { .on("GET", () => {
if (firstPoll) { if (firstPoll) {
firstPoll = false; firstPoll = false;
return ""; return "";
} }
return new HttpResponse(204, "No Content", ""); return new HttpResponse(204, "No Content", "");
}) })
.on("DELETE", (r) => new HttpResponse(202)); .on("DELETE", () => new HttpResponse(202));
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
@ -392,7 +390,7 @@ describe("HttpConnection", () => {
it("fails to start if negotiate redirects more than 100 times", async () => { it("fails to start if negotiate redirects more than 100 times", async () => {
const httpClient = new TestHttpClient() const httpClient = new TestHttpClient()
.on("POST", /negotiate$/, (r) => ({ url: "https://another.domain.url/chat" })); .on("POST", /negotiate$/, () => ({ url: "https://another.domain.url/chat" }));
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
@ -441,7 +439,7 @@ describe("HttpConnection", () => {
} }
return new HttpResponse(204, "No Content", ""); return new HttpResponse(204, "No Content", "");
}) })
.on("DELETE", (r) => new HttpResponse(202)); .on("DELETE", () => new HttpResponse(202));
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
@ -481,7 +479,7 @@ describe("HttpConnection", () => {
} }
}, },
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => ({ connectionId: "42", availableTransports: [availableTransport] })) .on("POST", () => ({ connectionId: "42", availableTransports: [availableTransport] }))
.on("GET", (r) => { .on("GET", (r) => {
httpClientGetCount++; httpClientGetCount++;
// tslint:disable-next-line:no-string-literal // tslint:disable-next-line:no-string-literal
@ -500,7 +498,7 @@ describe("HttpConnection", () => {
throw new Error("fail"); throw new Error("fail");
} }
}) })
.on("DELETE", (r) => new HttpResponse(202)), .on("DELETE", () => new HttpResponse(202)),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options); const connection = new HttpConnection("http://tempuri.org", options);
@ -521,8 +519,8 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => ({ connectionId: "42", availableTransports: [availableTransport] })) .on("POST", () => ({ connectionId: "42", availableTransports: [availableTransport] }))
.on("GET", (r) => { .on("GET", () => {
httpClientGetCount++; httpClientGetCount++;
if (httpClientGetCount === 1) { if (httpClientGetCount === 1) {
// First long polling request must succeed so start completes // First long polling request must succeed so start completes
@ -531,7 +529,7 @@ describe("HttpConnection", () => {
throw new Error("fail"); throw new Error("fail");
} }
}) })
.on("DELETE", (r) => new HttpResponse(202)), .on("DELETE", () => new HttpResponse(202)),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options); const connection = new HttpConnection("http://tempuri.org", options);
@ -549,7 +547,7 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => ({ connectionId: "42", availableTransports: [serverSentEventsTransport] })), .on("POST", () => ({ connectionId: "42", availableTransports: [serverSentEventsTransport] })),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options); const connection = new HttpConnection("http://tempuri.org", options);
@ -565,12 +563,12 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient() httpClient: new TestHttpClient()
.on("POST", (r) => ({ connectionId: "42", availableTransports: [webSocketsTransport] })), .on("POST", () => ({ connectionId: "42", availableTransports: [webSocketsTransport] })),
} as IHttpConnectionOptions; } as IHttpConnectionOptions;
const connection = new HttpConnection("http://tempuri.org", options); const connection = new HttpConnection("http://tempuri.org", options);
expect(connection.start(TransferFormat.Text)) await expect(connection.start(TransferFormat.Text))
.rejects .rejects
.toThrow("Unable to initialize any of the available transports."); .toThrow("Unable to initialize any of the available transports.");
}); });
@ -584,7 +582,7 @@ describe("HttpConnection", () => {
it("uses global WebSocket if defined", async () => { it("uses global WebSocket if defined", async () => {
// tslint:disable-next-line:no-string-literal // tslint:disable-next-line:no-string-literal
global["WebSocket"] = class WebSocket { global["WebSocket"] = class WebSocket {
constructor(url: string, protocols?: string | string[]) { constructor() {
throw new Error("WebSocket constructor called."); throw new Error("WebSocket constructor called.");
} }
}; };
@ -609,7 +607,7 @@ describe("HttpConnection", () => {
let eventSourceConstructorCalled: boolean = false; let eventSourceConstructorCalled: boolean = false;
// tslint:disable-next-line:no-string-literal // tslint:disable-next-line:no-string-literal
global["EventSource"] = class EventSource { global["EventSource"] = class EventSource {
constructor(url: string, eventSourceInitDict?: EventSourceInit) { constructor() {
eventSourceConstructorCalled = true; eventSourceConstructorCalled = true;
throw new Error("EventSource constructor called."); throw new Error("EventSource constructor called.");
} }
@ -617,7 +615,7 @@ describe("HttpConnection", () => {
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
httpClient: new TestHttpClient().on("POST", (r) => { httpClient: new TestHttpClient().on("POST", () => {
return { return {
availableTransports: [ availableTransports: [
{ transport: "ServerSentEvents", transferFormats: ["Text"] }, { transport: "ServerSentEvents", transferFormats: ["Text"] },
@ -643,17 +641,19 @@ describe("HttpConnection", () => {
it("uses EventSource constructor from options if provided", async () => { it("uses EventSource constructor from options if provided", async () => {
let eventSourceConstructorCalled: boolean = false; let eventSourceConstructorCalled: boolean = false;
const customEventSourceType = class EventSource { class TestEventSource {
constructor(url: string, eventSourceInitDict?: EventSourceInit) { // The "_" prefix tell TypeScript not to worry about unused parameter, but tslint doesn't like it.
// tslint:disable-next-line:variable-name
constructor(_url: string, _eventSourceInitDict: EventSourceInit) {
eventSourceConstructorCalled = true; eventSourceConstructorCalled = true;
throw new Error("EventSource constructor called."); throw new Error("EventSource constructor called.");
} }
}; }
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
EventSource: customEventSourceType as EventSourceConstructor, EventSource: TestEventSource as EventSourceConstructor,
httpClient: new TestHttpClient().on("POST", (r) => { httpClient: new TestHttpClient().on("POST", () => {
return { return {
availableTransports: [ availableTransports: [
{ transport: "ServerSentEvents", transferFormats: ["Text"] }, { transport: "ServerSentEvents", transferFormats: ["Text"] },
@ -674,15 +674,17 @@ describe("HttpConnection", () => {
}); });
it("uses WebSocket constructor from options if provided", async () => { it("uses WebSocket constructor from options if provided", async () => {
const customWebSocketType = class WebSocket { class TestWebSocket {
constructor(url: string, protocols?: string | string[]) { // The "_" prefix tell TypeScript not to worry about unused parameter, but tslint doesn't like it.
// tslint:disable-next-line:variable-name
constructor(_url: string, _protocols?: string | string[]) {
throw new Error("WebSocket constructor called."); throw new Error("WebSocket constructor called.");
} }
}; }
const options: IHttpConnectionOptions = { const options: IHttpConnectionOptions = {
...commonOptions, ...commonOptions,
WebSocket: customWebSocketType as WebSocketConstructor, WebSocket: TestWebSocket,
skipNegotiation: true, skipNegotiation: true,
transport: HttpTransportType.WebSockets, transport: HttpTransportType.WebSockets,
} as IHttpConnectionOptions; } as IHttpConnectionOptions;

View File

@ -88,7 +88,9 @@ describe("HubConnection", () => {
const hubConnection = createHubConnection(connection); const hubConnection = createHubConnection(connection);
try { try {
const invokePromise = hubConnection.send("testMethod", "arg", 42) // We don't actually care to wait for the send.
// tslint:disable-next-line:no-floating-promises
hubConnection.send("testMethod", "arg", 42)
.catch((_) => { }); // Suppress exception and unhandled promise rejection warning. .catch((_) => { }); // Suppress exception and unhandled promise rejection warning.
// Verify the message is sent // Verify the message is sent
@ -103,7 +105,7 @@ describe("HubConnection", () => {
}); });
} finally { } finally {
// Close the connection // Close the connection
hubConnection.stop(); await hubConnection.stop();
} }
}); });
}); });
@ -114,7 +116,9 @@ describe("HubConnection", () => {
const hubConnection = createHubConnection(connection); const hubConnection = createHubConnection(connection);
try { try {
const invokePromise = hubConnection.invoke("testMethod", "arg", 42) // We don't actually care to wait for the send.
// tslint:disable-next-line:no-floating-promises
hubConnection.invoke("testMethod", "arg", 42)
.catch((_) => { }); // Suppress exception and unhandled promise rejection warning. .catch((_) => { }); // Suppress exception and unhandled promise rejection warning.
// Verify the message is sent // Verify the message is sent
@ -131,7 +135,7 @@ describe("HubConnection", () => {
} finally { } finally {
// Close the connection // Close the connection
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -153,7 +157,7 @@ describe("HubConnection", () => {
// message only contained handshake response // message only contained handshake response
expect(protocolCalled).toEqual(false); expect(protocolCalled).toEqual(false);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -176,7 +180,7 @@ describe("HubConnection", () => {
// message only contained handshake response // message only contained handshake response
expect(protocolCalled).toEqual(false); expect(protocolCalled).toEqual(false);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -204,7 +208,7 @@ describe("HubConnection", () => {
// left over data is the message pack message // left over data is the message pack message
expect(receivedProcotolData!.byteLength).toEqual(102); expect(receivedProcotolData!.byteLength).toEqual(102);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -223,7 +227,7 @@ describe("HubConnection", () => {
expect(receivedProcotolData).toEqual("{\"type\":6}" + TextMessageFormat.RecordSeparator); expect(receivedProcotolData).toEqual("{\"type\":6}" + TextMessageFormat.RecordSeparator);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -239,7 +243,7 @@ describe("HubConnection", () => {
await expect(invokePromise).rejects.toThrow("foo"); await expect(invokePromise).rejects.toThrow("foo");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -255,7 +259,7 @@ describe("HubConnection", () => {
expect(await invokePromise).toBe("foo"); expect(await invokePromise).toBe("foo");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -267,9 +271,9 @@ describe("HubConnection", () => {
connection.receiveHandshakeResponse(); connection.receiveHandshakeResponse();
const invokePromise = hubConnection.invoke("testMethod"); const invokePromise = hubConnection.invoke("testMethod");
hubConnection.stop(); await hubConnection.stop();
expect(invokePromise).rejects.toThrow("Invocation canceled due to connection being closed."); await expect(invokePromise).rejects.toThrow("Invocation canceled due to connection being closed.");
}); });
it("completes pending invocations when connection is lost", async () => { it("completes pending invocations when connection is lost", async () => {
@ -283,9 +287,9 @@ describe("HubConnection", () => {
// Typically this would be called by the transport // Typically this would be called by the transport
connection.onclose!(new Error("Connection lost")); connection.onclose!(new Error("Connection lost"));
expect(invokePromise).rejects.toThrow("Connection lost"); await expect(invokePromise).rejects.toThrow("Connection lost");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
}); });
@ -314,7 +318,7 @@ describe("HubConnection", () => {
expect(warnings).toEqual(["No client method with the name 'message' found."]); expect(warnings).toEqual(["No client method with the name 'message' found."]);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -346,7 +350,7 @@ describe("HubConnection", () => {
expect(warnings).toEqual(["No client method with the name 'message' found."]); expect(warnings).toEqual(["No client method with the name 'message' found."]);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -382,7 +386,7 @@ describe("HubConnection", () => {
expect(count).toBe(2); expect(count).toBe(2);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -418,7 +422,7 @@ describe("HubConnection", () => {
expect(count).toBe(3); expect(count).toBe(3);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -443,7 +447,7 @@ describe("HubConnection", () => {
expect(count).toBe(1); expect(count).toBe(1);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -466,7 +470,7 @@ describe("HubConnection", () => {
expect(value).toBe("test"); expect(value).toBe("test");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -481,7 +485,7 @@ describe("HubConnection", () => {
expect(closeError!.message).toEqual("Server returned handshake error: Error!"); expect(closeError!.message).toEqual("Server returned handshake error: Error!");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -505,7 +509,7 @@ describe("HubConnection", () => {
expect(isClosed).toEqual(true); expect(isClosed).toEqual(true);
expect(closeError).toBeUndefined(); expect(closeError).toBeUndefined();
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -530,7 +534,7 @@ describe("HubConnection", () => {
expect(isClosed).toEqual(true); expect(isClosed).toEqual(true);
expect(closeError!.message).toEqual("Server returned an error on close: Error!"); expect(closeError!.message).toEqual("Server returned an error on close: Error!");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -556,7 +560,7 @@ describe("HubConnection", () => {
expect(numInvocations1).toBe(1); expect(numInvocations1).toBe(1);
expect(numInvocations2).toBe(1); expect(numInvocations2).toBe(1);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -590,7 +594,7 @@ describe("HubConnection", () => {
expect(numInvocations).toBe(1); expect(numInvocations).toBe(1);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -602,7 +606,7 @@ describe("HubConnection", () => {
hubConnection.on("message", (t) => { }); hubConnection.on("message", (t) => { });
hubConnection.on("message", () => { }); hubConnection.on("message", () => { });
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -647,7 +651,7 @@ describe("HubConnection", () => {
hubConnection.off(null!, () => { }); hubConnection.off(null!, () => { });
hubConnection.off(undefined!, () => { }); hubConnection.off(undefined!, () => { });
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
}); });
@ -658,7 +662,7 @@ describe("HubConnection", () => {
const hubConnection = createHubConnection(connection); const hubConnection = createHubConnection(connection);
try { try {
const invokePromise = hubConnection.stream("testStream", "arg", 42); hubConnection.stream("testStream", "arg", 42);
// Verify the message is sent // Verify the message is sent
expect(connection.sentData.length).toBe(1); expect(connection.sentData.length).toBe(1);
@ -673,9 +677,9 @@ describe("HubConnection", () => {
}); });
// Close the connection // Close the connection
hubConnection.stop(); await hubConnection.stop();
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -691,9 +695,9 @@ describe("HubConnection", () => {
connection.receive({ type: MessageType.Completion, invocationId: connection.lastInvocationId, error: "foo" }); connection.receive({ type: MessageType.Completion, invocationId: connection.lastInvocationId, error: "foo" });
expect(observer.completed).rejects.toThrow("Error: foo"); await expect(observer.completed).rejects.toThrow("Error: foo");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -711,7 +715,7 @@ describe("HubConnection", () => {
expect(await observer.completed).toEqual([]); expect(await observer.completed).toEqual([]);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -723,11 +727,11 @@ describe("HubConnection", () => {
const observer = new TestObserver(); const observer = new TestObserver();
hubConnection.stream<any>("testMethod") hubConnection.stream<any>("testMethod")
.subscribe(observer); .subscribe(observer);
hubConnection.stop(); await hubConnection.stop();
expect(observer.completed).rejects.toThrow("Error: Invocation canceled due to connection being closed."); await expect(observer.completed).rejects.toThrow("Error: Invocation canceled due to connection being closed.");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -743,9 +747,9 @@ describe("HubConnection", () => {
// Typically this would be called by the transport // Typically this would be called by the transport
connection.onclose!(new Error("Connection lost")); connection.onclose!(new Error("Connection lost"));
expect(observer.completed).rejects.toThrow("Error: Connection lost"); await expect(observer.completed).rejects.toThrow("Error: Connection lost");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -771,7 +775,7 @@ describe("HubConnection", () => {
connection.receive({ type: MessageType.Completion, invocationId: connection.lastInvocationId }); connection.receive({ type: MessageType.Completion, invocationId: connection.lastInvocationId });
expect(await observer.completed).toEqual([1, 2, 3]); expect(await observer.completed).toEqual([1, 2, 3]);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -780,13 +784,13 @@ describe("HubConnection", () => {
const hubConnection = createHubConnection(connection); const hubConnection = createHubConnection(connection);
try { try {
const observer = hubConnection.stream("testMethod").subscribe(NullSubscriber.instance); hubConnection.stream("testMethod").subscribe(NullSubscriber.instance);
// Typically this would be called by the transport // Typically this would be called by the transport
// triggers observer.error() // triggers observer.error()
connection.onclose!(new Error("Connection lost")); connection.onclose!(new Error("Connection lost"));
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -795,17 +799,17 @@ describe("HubConnection", () => {
const hubConnection = createHubConnection(connection); const hubConnection = createHubConnection(connection);
try { try {
const observer = hubConnection.stream("testMethod").subscribe(NullSubscriber.instance); hubConnection.stream("testMethod").subscribe(NullSubscriber.instance);
// Send completion to trigger observer.complete() // Send completion to trigger observer.complete()
// Expectation is connection.receive will not to throw // Expectation is connection.receive will not to throw
connection.receive({ type: MessageType.Completion, invocationId: connection.lastInvocationId }); connection.receive({ type: MessageType.Completion, invocationId: connection.lastInvocationId });
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
it("can be canceled", () => { it("can be canceled", async () => {
const connection = new TestConnection(); const connection = new TestConnection();
const hubConnection = createHubConnection(connection); const hubConnection = createHubConnection(connection);
try { try {
@ -831,7 +835,7 @@ describe("HubConnection", () => {
type: MessageType.CancelInvocation, type: MessageType.CancelInvocation,
}); });
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
}); });
@ -848,7 +852,7 @@ describe("HubConnection", () => {
connection.onclose!(); connection.onclose!();
expect(invocations).toBe(2); expect(invocations).toBe(2);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -863,7 +867,7 @@ describe("HubConnection", () => {
connection.onclose!(new Error("Test error.")); connection.onclose!(new Error("Test error."));
expect(error!.message).toBe("Test error."); expect(error!.message).toBe("Test error.");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -877,7 +881,7 @@ describe("HubConnection", () => {
connection.onclose!(); connection.onclose!();
// expect no errors // expect no errors
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -892,7 +896,7 @@ describe("HubConnection", () => {
expect(state).toBe(HubConnectionState.Disconnected); expect(state).toBe(HubConnectionState.Disconnected);
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
}); });
@ -911,7 +915,7 @@ describe("HubConnection", () => {
expect(await invokePromise).toBe("foo"); expect(await invokePromise).toBe("foo");
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -930,13 +934,13 @@ describe("HubConnection", () => {
await pingAndWait(connection); await pingAndWait(connection);
} }
connection.stop(); await connection.stop();
const error = await p.promise; const error = await p.promise;
expect(error).toBeUndefined(); expect(error).toBeUndefined();
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -959,13 +963,13 @@ describe("HubConnection", () => {
await pingAndWait(connection); await pingAndWait(connection);
} }
connection.stop(); await connection.stop();
const error = await p.promise; const error = await p.promise;
expect(error).toBeUndefined(); expect(error).toBeUndefined();
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
@ -984,7 +988,7 @@ describe("HubConnection", () => {
expect(error).toEqual(new Error("Server timeout elapsed without receiving a message from the server.")); expect(error).toEqual(new Error("Server timeout elapsed without receiving a message from the server."));
} finally { } finally {
hubConnection.stop(); await hubConnection.stop();
} }
}); });
}); });

View File

@ -13,15 +13,6 @@ import { NullLogger } from "../src/Loggers";
import { TestHttpClient } from "./TestHttpClient"; import { TestHttpClient } from "./TestHttpClient";
import { PromiseSource } from "./Utils"; import { PromiseSource } from "./Utils";
const allTransportsNegotiateResponse = {
availableTransports: [
{ transport: "WebSockets", transferFormats: ["Text", "Binary"] },
{ transport: "ServerSentEvents", transferFormats: ["Text"] },
{ transport: "LongPolling", transferFormats: ["Text", "Binary"] },
],
connectionId: "abc123",
};
const longPollingNegotiateResponse = { const longPollingNegotiateResponse = {
availableTransports: [ availableTransports: [
{ transport: "LongPolling", transferFormats: ["Text", "Binary"] }, { transport: "LongPolling", transferFormats: ["Text", "Binary"] },
@ -80,11 +71,6 @@ describe("HubConnectionBuilder", () => {
it("can configure transport type", async () => { it("can configure transport type", async () => {
const protocol = new TestProtocol(); const protocol = new TestProtocol();
const pollSent = new PromiseSource<HttpRequest>();
const pollCompleted = new PromiseSource<HttpResponse>();
const negotiateReceived = new PromiseSource<HttpRequest>();
const testClient = createTestClient(pollSent, pollCompleted.promise, allTransportsNegotiateResponse);
const builder = createConnectionBuilder() const builder = createConnectionBuilder()
.withUrl("http://example.com", HttpTransportType.WebSockets) .withUrl("http://example.com", HttpTransportType.WebSockets)
.withHubProtocol(protocol); .withHubProtocol(protocol);

View File

@ -1,13 +1,13 @@
import { HttpError, TimeoutError } from "../src/Errors"; // 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.
import { HttpResponse } from "../src/HttpClient"; import { HttpResponse } from "../src/HttpClient";
import { LogLevel } from "../src/ILogger";
import { TransferFormat } from "../src/ITransport"; import { TransferFormat } from "../src/ITransport";
import { NullLogger } from "../src/Loggers"; import { NullLogger } from "../src/Loggers";
import { LongPollingTransport } from "../src/LongPollingTransport"; import { LongPollingTransport } from "../src/LongPollingTransport";
import { ConsoleLogger } from "../src/Utils";
import { TestHttpClient } from "./TestHttpClient"; import { TestHttpClient } from "./TestHttpClient";
import { delay, PromiseSource, SyncPoint } from "./Utils"; import { PromiseSource, SyncPoint } from "./Utils";
describe("LongPollingTransport", () => { describe("LongPollingTransport", () => {
it("shuts down polling by aborting in-progress request", async () => { it("shuts down polling by aborting in-progress request", async () => {
@ -29,7 +29,7 @@ describe("LongPollingTransport", () => {
return new HttpResponse(200); return new HttpResponse(200);
} }
}) })
.on("DELETE", (r) => new HttpResponse(202)); .on("DELETE", () => new HttpResponse(202));
const transport = new LongPollingTransport(client, undefined, NullLogger.instance, false); const transport = new LongPollingTransport(client, undefined, NullLogger.instance, false);
await transport.connect("http://example.com", TransferFormat.Text); await transport.connect("http://example.com", TransferFormat.Text);
@ -42,17 +42,16 @@ describe("LongPollingTransport", () => {
it("204 server response stops polling and raises onClose", async () => { it("204 server response stops polling and raises onClose", async () => {
let firstPoll = true; let firstPoll = true;
let onCloseCalled = false;
const client = new TestHttpClient() const client = new TestHttpClient()
.on("GET", async (r) => { .on("GET", async () => {
if (firstPoll) { if (firstPoll) {
firstPoll = false; firstPoll = false;
return new HttpResponse(200); return new HttpResponse(200);
} else { } else {
// A 204 response will stop the long polling transport // A 204 response will stop the long polling transport
return new HttpResponse(204); return new HttpResponse(204);
} }
}); });
const transport = new LongPollingTransport(client, undefined, NullLogger.instance, false); const transport = new LongPollingTransport(client, undefined, NullLogger.instance, false);
const stopPromise = makeClosedPromise(transport); const stopPromise = makeClosedPromise(transport);
@ -83,7 +82,7 @@ describe("LongPollingTransport", () => {
await deleteSyncPoint.waitToContinue(); await deleteSyncPoint.waitToContinue();
return new HttpResponse(202); return new HttpResponse(202);
}); });
const transport = new LongPollingTransport(httpClient, undefined, NullLogger.instance, false); const transport = new LongPollingTransport(httpClient, undefined, NullLogger.instance, false);
await transport.connect("http://tempuri.org", TransferFormat.Text); await transport.connect("http://tempuri.org", TransferFormat.Text);
@ -119,4 +118,4 @@ function makeClosedPromise(transport: LongPollingTransport): Promise<void> {
} }
}; };
return closed.promise; return closed.promise;
} }

View File

@ -60,4 +60,4 @@ export class SyncPoint {
this.atSyncPoint.resolve(); this.atSyncPoint.resolve();
return this.continueFromSyncPoint.promise; return this.continueFromSyncPoint.promise;
} }
} }

View File

@ -6,6 +6,8 @@
"interface-name": false, "interface-name": false,
"unified-signatures": false, "unified-signatures": false,
"max-classes-per-file": false, "max-classes-per-file": false,
"no-floating-promises": true,
"no-unused-variable": [true, {"ignore-pattern": "^_"}],
"no-empty": false, "no-empty": false,
"no-bitwise": false, "no-bitwise": false,
"no-console": false "no-console": false