From ed84760f0e4f2cffe17cf58f27ced38cea0c78d4 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 9 Feb 2021 17:00:54 +1100 Subject: [PATCH] add a tslint rule to forbid use of async without await --- ts/components/session/RegistrationTabs.tsx | 12 +++---- ts/components/session/SessionSeedModal.tsx | 4 +-- .../conversation/SessionCompositionBox.tsx | 4 +-- .../conversation/SessionConversation.tsx | 2 +- .../conversation/SessionMessagesList.tsx | 4 +-- .../session/conversation/SessionRecording.tsx | 10 +++--- .../conversation/SessionRightPanel.tsx | 22 ++++++------ ts/models/conversation.ts | 7 ++-- ts/receiver/queuedJob.ts | 2 +- ts/receiver/receiver.ts | 27 +++++++------- ts/session/group/index.ts | 8 ++--- ts/session/snode_api/swarmPolling.ts | 2 +- ts/test/session/integration/common.ts | 12 +++---- .../unit/crypto/MessageEncrypter_test.ts | 6 ++-- .../unit/receiving/ClosedGroupUpdates_test.ts | 19 +++------- .../session/unit/sending/MessageQueue_test.ts | 26 +++++++------- .../unit/sending/PendingMessageCache_test.ts | 3 +- ts/test/session/unit/utils/JobQueue_test.ts | 7 ++-- ts/test/session/unit/utils/Messages_test.ts | 6 ++-- ts/test/session/unit/utils/Promise_test.ts | 26 +++++++------- ts/test/session/unit/utils/String_test.ts | 36 +++++++++---------- ts/test/session/unit/utils/SyncUtils_test.ts | 13 +++---- ts/test/tslint.json | 5 --- ts/test/util/blockedNumberController_test.ts | 16 +++++---- tslint.json | 23 +----------- 25 files changed, 133 insertions(+), 169 deletions(-) diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx index e4d3ce1b2..0bf51680b 100644 --- a/ts/components/session/RegistrationTabs.tsx +++ b/ts/components/session/RegistrationTabs.tsx @@ -131,8 +131,8 @@ export class RegistrationTabs extends React.Component { } public componentDidMount() { - this.generateMnemonicAndKeyPair().ignore(); - this.resetRegistration().ignore(); + void this.generateMnemonicAndKeyPair(); + void this.resetRegistration(); } public render() { @@ -345,7 +345,7 @@ export class RegistrationTabs extends React.Component { { if (signUpMode === SignUpMode.Default) { - this.onSignUpGenerateSessionIDClick().ignore(); + this.onSignUpGenerateSessionIDClick(); } else { this.onSignUpGetStartedClick(); } @@ -357,7 +357,7 @@ export class RegistrationTabs extends React.Component { ); } - private async onSignUpGenerateSessionIDClick() { + private onSignUpGenerateSessionIDClick() { this.setState( { signUpMode: SignUpMode.SessionIDShown, @@ -375,7 +375,7 @@ export class RegistrationTabs extends React.Component { } private onCompleteSignUpClick() { - this.register('english').ignore(); + void this.register('english'); } private renderSignIn() { @@ -541,7 +541,7 @@ export class RegistrationTabs extends React.Component { private handleContinueYourSessionClick() { if (this.state.signInMode === SignInMode.UsingRecoveryPhrase) { - this.register('english').ignore(); + void this.register('english'); } } diff --git a/ts/components/session/SessionSeedModal.tsx b/ts/components/session/SessionSeedModal.tsx index 0852a9411..539894e68 100644 --- a/ts/components/session/SessionSeedModal.tsx +++ b/ts/components/session/SessionSeedModal.tsx @@ -50,8 +50,8 @@ class SessionSeedModalInner extends React.Component { public render() { const i18n = window.i18n; - this.checkHasPassword(); - this.getRecoveryPhrase().ignore(); + void this.checkHasPassword(); + void this.getRecoveryPhrase(); const { onClose } = this.props; const { hasPassword, passwordValid } = this.state; diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx index fb3b723c5..95f390601 100644 --- a/ts/components/session/conversation/SessionCompositionBox.tsx +++ b/ts/components/session/conversation/SessionCompositionBox.tsx @@ -520,7 +520,7 @@ export class SessionCompositionBox extends React.Component { } if (firstLink !== this.state.stagedLinkPreview?.url) { // trigger fetching of link preview data and image - void this.fetchLinkPreview(firstLink); + this.fetchLinkPreview(firstLink); } // if the fetch did not start yet, just don't show anything @@ -553,7 +553,7 @@ export class SessionCompositionBox extends React.Component { return <>; } - private async fetchLinkPreview(firstLink: string) { + private fetchLinkPreview(firstLink: string) { // mark the link preview as loading, no data are set yet this.setState({ stagedLinkPreview: { diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index 2cb68faa0..eba3c7e61 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -824,7 +824,7 @@ export class SessionConversation extends React.Component { } } - private async showMessageDetails(messageProps: any) { + private showMessageDetails(messageProps: any) { messageProps.onDeleteMessage = async (id: string) => { await this.deleteMessagesById([id], false); this.setState({ messageDetailShowProps: undefined }); diff --git a/ts/components/session/conversation/SessionMessagesList.tsx b/ts/components/session/conversation/SessionMessagesList.tsx index 3e84edc94..a4a9a0c26 100644 --- a/ts/components/session/conversation/SessionMessagesList.tsx +++ b/ts/components/session/conversation/SessionMessagesList.tsx @@ -41,7 +41,7 @@ interface Props { count: number; }) => void; replyToMessage: (messageId: number) => Promise; - showMessageDetails: (messageProps: any) => Promise; + showMessageDetails: (messageProps: any) => void; onClickAttachment: (attachment: any, message: any) => void; onDownloadAttachment: ({ attachment }: { attachment: any }) => void; onDeleteSelectedMessages: () => Promise; @@ -326,7 +326,7 @@ export class SessionMessagesList extends React.Component { messageProps.onReply = this.props.replyToMessage; messageProps.onShowDetail = async () => { const messageDetailsProps = await message.getPropsForMessageDetail(); - void this.props.showMessageDetails(messageDetailsProps); + this.props.showMessageDetails(messageDetailsProps); }; messageProps.onClickAttachment = (attachment: AttachmentType) => { diff --git a/ts/components/session/conversation/SessionRecording.tsx b/ts/components/session/conversation/SessionRecording.tsx index 053e808d4..065740865 100644 --- a/ts/components/session/conversation/SessionRecording.tsx +++ b/ts/components/session/conversation/SessionRecording.tsx @@ -122,9 +122,9 @@ class SessionRecordingInner extends React.Component { }; } - public async componentWillMount() { + public componentWillMount() { // This turns on the microphone on the system. Later we need to turn it off. - await this.initiateRecordingStream(); + this.initiateRecordingStream(); } public componentDidMount() { @@ -309,7 +309,7 @@ class SessionRecordingInner extends React.Component { } } - private async stopRecording() { + private stopRecording() { this.setState({ isRecording: false, isPaused: true, @@ -436,7 +436,7 @@ class SessionRecordingInner extends React.Component { this.props.sendVoiceMessage(audioBlob); } - private async initiateRecordingStream() { + private initiateRecordingStream() { navigator.getUserMedia( { audio: true }, this.onRecordingStream, @@ -462,7 +462,7 @@ class SessionRecordingInner extends React.Component { streamParams.stream.getTracks().forEach((track: any) => track.stop); // Stop recording - await this.stopRecording(); + this.stopRecording(); } private async onRecordingStream(stream: any) { diff --git a/ts/components/session/conversation/SessionRightPanel.tsx b/ts/components/session/conversation/SessionRightPanel.tsx index 47164cd0b..07c97d0cd 100644 --- a/ts/components/session/conversation/SessionRightPanel.tsx +++ b/ts/components/session/conversation/SessionRightPanel.tsx @@ -69,23 +69,23 @@ class SessionRightPanel extends React.Component { } public componentWillMount() { - this.getMediaGalleryProps() - .then(({ documents, media, onItemClick }) => { + void this.getMediaGalleryProps().then( + ({ documents, media, onItemClick }) => { this.setState({ documents, media, onItemClick, }); - }) - .ignore(); + } + ); } public componentDidUpdate() { const mediaScanInterval = 1000; setTimeout(() => { - this.getMediaGalleryProps() - .then(({ documents, media, onItemClick }) => { + void this.getMediaGalleryProps().then( + ({ documents, media, onItemClick }) => { const { documents: oldDocs, media: oldMedias } = this.state; if ( oldDocs.length !== documents.length || @@ -97,8 +97,8 @@ class SessionRightPanel extends React.Component { onItemClick, }); } - }) - .ignore(); + } + ); }, mediaScanInterval); } @@ -193,7 +193,7 @@ class SessionRightPanel extends React.Component { } ); - const saveAttachment = async ({ attachment, message }: any = {}) => { + const saveAttachment = ({ attachment, message }: any = {}) => { const timestamp = message.received_at; save({ attachment, @@ -203,10 +203,10 @@ class SessionRightPanel extends React.Component { }); }; - const onItemClick = async ({ message, attachment, type }: any) => { + const onItemClick = ({ message, attachment, type }: any) => { switch (type) { case 'documents': { - saveAttachment({ message, attachment }).ignore(); + saveAttachment({ message, attachment }); break; } diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 6605209e3..a2619d3f5 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -422,7 +422,7 @@ export class ConversationModel extends Backbone.Model { if (!registeredMessage || !registeredMessage.message) { return null; } - const model = registeredMessage.message as MessageModel; + const model = registeredMessage.message; await model.setIsPublic(true); await model.setServerId(serverId); await model.setServerTimestamp(serverTimestamp); @@ -1298,7 +1298,10 @@ export class ConversationModel extends Backbone.Model { } } public async setSubscriberCount(count: number) { - this.set({ subscriberCount: count }); + if (this.get('subscriberCount') !== count) { + this.set({ subscriberCount: count }); + await this.commit(); + } // Not sure if we care about updating the database } public async setGroupNameAndAvatar(name: any, avatarPath: any) { diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts index a30d2f264..88152bf76 100644 --- a/ts/receiver/queuedJob.ts +++ b/ts/receiver/queuedJob.ts @@ -115,7 +115,7 @@ async function copyFromQuotedMessage( window.log.info( `Looking for the message id : ${id}, attempt: ${attemptCount + 1}` ); - copyFromQuotedMessage(msg, quote, attemptCount + 1).ignore(); + void copyFromQuotedMessage(msg, quote, attemptCount + 1); }, attemptCount * attemptCount * 500); } else { window.log.warn( diff --git a/ts/receiver/receiver.ts b/ts/receiver/receiver.ts index e4fc39803..3524477b7 100644 --- a/ts/receiver/receiver.ts +++ b/ts/receiver/receiver.ts @@ -52,7 +52,7 @@ class EnvelopeQueue { // Last pending promise private pending: Promise = Promise.resolve(); - public async add(task: any): Promise { + public add(task: any): void { this.count += 1; const promise = this.pending.then(task, task); this.pending = promise; @@ -85,16 +85,16 @@ function queueEnvelope(envelope: EnvelopePlus) { `queueEnvelope ${id}` ); - const promise = envelopeQueue.add(taskWithTimeout); - - promise.catch((error: any) => { + try { + envelopeQueue.add(taskWithTimeout); + } catch (error) { window.log.error( 'queueEnvelope error handling envelope', id, ':', error && error.stack ? error.stack : error ); - }); + } } async function handleRequestDetail( @@ -154,10 +154,7 @@ async function handleRequestDetail( } } -export async function handleRequest( - body: any, - options: ReqOptions -): Promise { +export function handleRequest(body: any, options: ReqOptions): void { // tslint:disable-next-line no-promise-as-boolean const lastPromise = _.last(incomingMessagePromises) || Promise.resolve(); @@ -210,7 +207,7 @@ async function queueCached(item: any) { if (decrypted) { const payloadPlaintext = StringUtils.encode(decrypted, 'base64'); - await queueDecryptedEnvelope(envelope, payloadPlaintext); + queueDecryptedEnvelope(envelope, payloadPlaintext); } else { queueEnvelope(envelope); } @@ -236,7 +233,7 @@ async function queueCached(item: any) { } } -async function queueDecryptedEnvelope(envelope: any, plaintext: ArrayBuffer) { +function queueDecryptedEnvelope(envelope: any, plaintext: ArrayBuffer) { const id = getEnvelopeId(envelope); window.log.info('queueing decrypted envelope', id); @@ -245,14 +242,14 @@ async function queueDecryptedEnvelope(envelope: any, plaintext: ArrayBuffer) { task, `queueEncryptedEnvelope ${id}` ); - const promise = envelopeQueue.add(taskWithTimeout); - - return promise.catch(error => { + try { + envelopeQueue.add(taskWithTimeout); + } catch (error) { window.log.error( `queueDecryptedEnvelope error handling envelope ${id}:`, error && error.stack ? error.stack : error ); - }); + } } async function handleDecryptedEnvelope( diff --git a/ts/session/group/index.ts b/ts/session/group/index.ts index 80bc58282..cb9a6e1e9 100644 --- a/ts/session/group/index.ts +++ b/ts/session/group/index.ts @@ -310,9 +310,7 @@ export async function updateOrCreateClosedGroup(details: GroupInfo) { } export async function leaveClosedGroup(groupId: string) { - const convo = ConversationController.getInstance().get( - groupId - ) as ConversationModel; + const convo = ConversationController.getInstance().get(groupId); if (!convo) { window.log.error('Cannot leave non-existing group'); @@ -334,7 +332,9 @@ export async function leaveClosedGroup(groupId: string) { } else { // otherwise, just the exclude ourself from the members and trigger an update with this convo.set({ left: true }); - members = (convo.get('members') || []).filter(m => m !== ourNumber.key); + members = (convo.get('members') || []).filter( + (m: string) => m !== ourNumber.key + ); admins = convo.get('groupAdmins') || []; } convo.set({ members }); diff --git a/ts/session/snode_api/swarmPolling.ts b/ts/session/snode_api/swarmPolling.ts index e5d32edf9..5ae433956 100644 --- a/ts/session/snode_api/swarmPolling.ts +++ b/ts/session/snode_api/swarmPolling.ts @@ -52,7 +52,7 @@ export class SwarmPolling { this.lastHashes = {}; } - public async start(): Promise { + public start(): void { this.loadGroupIds(); void this.pollForAllKeys(); } diff --git a/ts/test/session/integration/common.ts b/ts/test/session/integration/common.ts index 0772ddfe8..0bb5e1d23 100644 --- a/ts/test/session/integration/common.ts +++ b/ts/test/session/integration/common.ts @@ -1,6 +1,6 @@ // tslint:disable: no-implicit-dependencies -import { Application, SpectronClient } from 'spectron'; +import { Application } from 'spectron'; import path from 'path'; import url from 'url'; import http from 'http'; @@ -73,7 +73,7 @@ export class Common { } public static async closeToast(app: Application) { - app.client.element(CommonPage.toastCloseButton).click(); + await app.client.element(CommonPage.toastCloseButton).click(); } // a wrapper to work around electron/spectron bug @@ -219,7 +219,7 @@ export class Common { env?: string; }) { const app = await Common.startAndAssureCleanedApp(env); - await Common.startStubSnodeServer(); + Common.startStubSnodeServer(); if (recoveryPhrase && displayName) { await Common.restoreFromRecoveryPhrase(app, recoveryPhrase, displayName); @@ -562,7 +562,7 @@ export class Common { return `Test message from integration tests ${Date.now()}`; } - public static async startStubSnodeServer() { + public static startStubSnodeServer() { if (!Common.stubSnode) { Common.messages = {}; Common.stubSnode = http.createServer((request: any, response: any) => { @@ -684,7 +684,7 @@ export class Common { public static async stopStubSnodeServer() { if (Common.stubSnode) { - Common.stubSnode.close(); + await Common.stubSnode.close(); Common.stubSnode = null; } } @@ -695,7 +695,7 @@ export class Common { * @param str the string to search (not regex) * Note: getRenderProcessLogs() clears the app logs each calls. */ - public static async logsContains( + public static logsContains( renderLogs: Array<{ message: string }>, str: string, count?: number diff --git a/ts/test/session/unit/crypto/MessageEncrypter_test.ts b/ts/test/session/unit/crypto/MessageEncrypter_test.ts index c05dfb4b0..a3fcbc011 100644 --- a/ts/test/session/unit/crypto/MessageEncrypter_test.ts +++ b/ts/test/session/unit/crypto/MessageEncrypter_test.ts @@ -165,9 +165,9 @@ describe('MessageEncrypter', () => { .to.deep.equal(SignalService.Envelope.Type.UNIDENTIFIED_SENDER); }); - it('should throw an error for anything else than Fallback or ClosedGroup', async () => { + it('should throw an error for anything else than Fallback or ClosedGroup', () => { const data = crypto.randomBytes(10); - await expect( + expect( MessageEncrypter.encrypt( TestUtils.generateFakePubKey(), data, @@ -182,7 +182,7 @@ describe('MessageEncrypter', () => { describe('Session Protocol', () => { let sandboxSessionProtocol: sinon.SinonSandbox; - beforeEach(async () => { + beforeEach(() => { sandboxSessionProtocol = sinon.createSandbox(); sandboxSessionProtocol diff --git a/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts b/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts index 560b21c94..ca8224b26 100644 --- a/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts +++ b/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts @@ -1,22 +1,11 @@ +// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression + import chai from 'chai'; -import * as sinon from 'sinon'; import _ from 'lodash'; import { describe } from 'mocha'; -import { GroupUtils, PromiseUtils, UserUtils } from '../../../../session/utils'; -import { TestUtils } from '../../../../test/test-utils'; -import { - generateEnvelopePlusClosedGroup, - generateGroupUpdateNameChange, -} from '../../../test-utils/utils/envelope'; -import { handleClosedGroupControlMessage } from '../../../../receiver/closedGroups'; -import { ConversationController } from '../../../../session/conversations'; - -// tslint:disable-next-line: no-require-imports no-var-requires no-implicit-dependencies -const chaiAsPromised = require('chai-as-promised'); -chai.use(chaiAsPromised); - -const { expect } = chai; +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised as any); // tslint:disable-next-line: max-func-body-length describe('ClosedGroupUpdates', () => { diff --git a/ts/test/session/unit/sending/MessageQueue_test.ts b/ts/test/session/unit/sending/MessageQueue_test.ts index a7b5e4a85..6dd33aa27 100644 --- a/ts/test/session/unit/sending/MessageQueue_test.ts +++ b/ts/test/session/unit/sending/MessageQueue_test.ts @@ -1,3 +1,5 @@ +// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression + import chai from 'chai'; import * as sinon from 'sinon'; import _ from 'lodash'; @@ -15,9 +17,8 @@ import { MessageSender } from '../../../../session/sending'; import { PendingMessageCacheStub } from '../../../test-utils/stubs'; import { ClosedGroupMessage } from '../../../../session/messages/outgoing/content/data/group/ClosedGroupMessage'; -// tslint:disable-next-line: no-require-imports no-var-requires -const chaiAsPromised = require('chai-as-promised'); -chai.use(chaiAsPromised); +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised as any); const { expect } = chai; @@ -35,7 +36,7 @@ describe('MessageQueue', () => { // Message Sender Stubs let sendStub: sinon.SinonStub<[RawMessage, (number | undefined)?]>; - beforeEach(async () => { + beforeEach(() => { // Utils Stubs sandbox.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(ourNumber); @@ -65,7 +66,8 @@ describe('MessageQueue', () => { messageQueueStub.events.once('sendSuccess', done); }); await messageQueueStub.processPending(device); - await expect(successPromise).to.be.fulfilled; + // tslint:disable-next-line: no-unused-expression + expect(successPromise).to.eventually.be.fulfilled; }); it('should remove message from cache', async () => { @@ -88,7 +90,7 @@ describe('MessageQueue', () => { const messages = await pendingMessageCache.getForDevice(device); return messages.length === 0; }); - await expect(promise).to.be.fulfilled; + return promise.should.be.fulfilled; } }).timeout(15000); @@ -105,7 +107,6 @@ describe('MessageQueue', () => { }); await messageQueueStub.processPending(device); - await expect(eventPromise).to.be.fulfilled; const rawMessage = await eventPromise; expect(rawMessage.identifier).to.equal(message.identifier); @@ -130,7 +131,6 @@ describe('MessageQueue', () => { }); await messageQueueStub.processPending(device); - await expect(eventPromise).to.be.fulfilled; const [rawMessage, error] = await eventPromise; expect(rawMessage.identifier).to.equal(message.identifier); @@ -166,7 +166,7 @@ describe('MessageQueue', () => { }); describe('sendToGroup', () => { - it('should throw an error if invalid non-group message was passed', async () => { + it('should throw an error if invalid non-group message was passed', () => { // const chatMessage = TestUtils.generateChatMessage(); // await expect( // messageQueueStub.sendToGroup(chatMessage) @@ -174,7 +174,7 @@ describe('MessageQueue', () => { // Cannot happen with typescript as this function only accept group message now }); - describe('closed groups', async () => { + describe('closed groups', () => { it('can send to closed group', async () => { const members = TestUtils.generateFakePubKeys(4).map( p => new PubKey(p.key) @@ -194,7 +194,7 @@ describe('MessageQueue', () => { ); }); - describe('open groups', async () => { + describe('open groups', () => { let sendToOpenGroupStub: sinon.SinonStub< [OpenGroupMessage], Promise<{ serverId: number; serverTimestamp: number }> @@ -223,7 +223,7 @@ describe('MessageQueue', () => { }, 2000); await messageQueueStub.sendToGroup(message); - await expect(eventPromise).to.be.fulfilled; + return eventPromise.should.be.fulfilled; }); it('should emit a fail event if something went wrong', async () => { @@ -234,7 +234,7 @@ describe('MessageQueue', () => { }, 2000); await messageQueueStub.sendToGroup(message); - await expect(eventPromise).to.be.fulfilled; + return eventPromise.should.be.fulfilled; }); }); }); diff --git a/ts/test/session/unit/sending/PendingMessageCache_test.ts b/ts/test/session/unit/sending/PendingMessageCache_test.ts index 7e493b33d..d3cc81f17 100644 --- a/ts/test/session/unit/sending/PendingMessageCache_test.ts +++ b/ts/test/session/unit/sending/PendingMessageCache_test.ts @@ -1,3 +1,4 @@ +// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression import { expect } from 'chai'; import * as sinon from 'sinon'; import * as _ from 'lodash'; @@ -17,7 +18,7 @@ describe('PendingMessageCache', () => { let data: StorageItem; let pendingMessageCacheStub: PendingMessageCache; - beforeEach(async () => { + beforeEach(() => { // Stub out methods which touch the database const storageID = 'pendingMessages'; data = { diff --git a/ts/test/session/unit/utils/JobQueue_test.ts b/ts/test/session/unit/utils/JobQueue_test.ts index 1abb38b87..ecdc6e7fe 100644 --- a/ts/test/session/unit/utils/JobQueue_test.ts +++ b/ts/test/session/unit/utils/JobQueue_test.ts @@ -1,11 +1,12 @@ +// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression + import chai from 'chai'; import { v4 as uuid } from 'uuid'; import { JobQueue } from '../../../../session/utils/JobQueue'; import { TestUtils } from '../../../test-utils'; -// tslint:disable-next-line: no-require-imports no-var-requires -const chaiAsPromised = require('chai-as-promised'); -chai.use(chaiAsPromised); +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised as any); const { assert } = chai; diff --git a/ts/test/session/unit/utils/Messages_test.ts b/ts/test/session/unit/utils/Messages_test.ts index 57aaa699e..d34e217bb 100644 --- a/ts/test/session/unit/utils/Messages_test.ts +++ b/ts/test/session/unit/utils/Messages_test.ts @@ -17,9 +17,9 @@ import { import { MockConversation } from '../../../test-utils/utils'; import { ConfigurationMessage } from '../../../../session/messages/outgoing/content/ConfigurationMessage'; import { ConversationModel } from '../../../../models/conversation'; -// tslint:disable-next-line: no-require-imports no-var-requires -const chaiAsPromised = require('chai-as-promised'); -chai.use(chaiAsPromised); + +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised as any); const { expect } = chai; diff --git a/ts/test/session/unit/utils/Promise_test.ts b/ts/test/session/unit/utils/Promise_test.ts index 28ec57532..1bc04261c 100644 --- a/ts/test/session/unit/utils/Promise_test.ts +++ b/ts/test/session/unit/utils/Promise_test.ts @@ -1,11 +1,13 @@ +// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression + import chai from 'chai'; import * as sinon from 'sinon'; import { PromiseUtils } from '../../../../session/utils'; // tslint:disable-next-line: no-require-imports no-var-requires -const chaiAsPromised = require('chai-as-promised'); -chai.use(chaiAsPromised); +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised as any); const { expect } = chai; @@ -49,20 +51,20 @@ describe('Promise Utils', () => { }; const promise = PromiseUtils.poll(task, {}); + await promise; - await expect(promise).to.be.fulfilled; expect(pollSpy.callCount).to.equal(1); expect(completionSpy.callCount).to.equal(1); }); - it('can timeout a task', async () => { + it('can timeout a task', () => { // completionSpy will be called on done const completionSpy = sandbox.spy(); const task = (_done: any) => undefined; const promise = PromiseUtils.poll(task, { timeoutMs: 1 }); - await expect(promise).to.be.rejectedWith('Periodic check timeout'); + promise.should.eventually.be.rejectedWith('Periodic check timeout'); expect(pollSpy.callCount).to.equal(1); expect(completionSpy.callCount).to.equal(0); }); @@ -83,8 +85,8 @@ describe('Promise Utils', () => { }; const promise = PromiseUtils.poll(task, { timeoutMs: timeout, interval }); + await promise; - await expect(promise).to.be.fulfilled; expect(pollSpy.callCount).to.equal(1); expect(recurrenceSpy.callCount).to.equal(expectedRecurrences); }); @@ -103,19 +105,19 @@ describe('Promise Utils', () => { const promise = PromiseUtils.waitForTask(task); - await expect(promise).to.be.fulfilled; + await promise; expect(waitForTaskSpy.callCount).to.equal(1); expect(completionSpy.callCount).to.equal(1); }); - it('can timeout a task', async () => { + it('can timeout a task', () => { // completionSpy will be called on done const completionSpy = sandbox.spy(); const task = async (_done: any) => undefined; const promise = PromiseUtils.waitForTask(task, 1); - await expect(promise).to.be.rejectedWith('Task timed out.'); + promise.should.eventually.be.rejectedWith('Task timed out.'); expect(waitForTaskSpy.callCount).to.equal(1); expect(completionSpy.callCount).to.equal(0); }); @@ -125,16 +127,16 @@ describe('Promise Utils', () => { it('can wait for check', async () => { const check = () => true; const promise = PromiseUtils.waitUntil(check); + await promise; - await expect(promise).to.be.fulfilled; expect(waitUntilSpy.callCount).to.equal(1); }); - it('can timeout a check', async () => { + it('can timeout a check', () => { const check = () => false; const promise = PromiseUtils.waitUntil(check, 1); - await expect(promise).to.be.rejectedWith('Periodic check timeout'); + promise.should.eventually.be.rejectedWith('Periodic check timeout'); expect(waitUntilSpy.callCount).to.equal(1); }); }); diff --git a/ts/test/session/unit/utils/String_test.ts b/ts/test/session/unit/utils/String_test.ts index 5e42bf731..503a9023b 100644 --- a/ts/test/session/unit/utils/String_test.ts +++ b/ts/test/session/unit/utils/String_test.ts @@ -1,3 +1,4 @@ +// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression import chai from 'chai'; import ByteBuffer from 'bytebuffer'; @@ -5,15 +6,14 @@ import ByteBuffer from 'bytebuffer'; import { Encoding } from '../../../../session/utils/String'; import { StringUtils } from '../../../../session/utils'; -// tslint:disable-next-line: no-require-imports no-var-requires -const chaiAsPromised = require('chai-as-promised'); -chai.use(chaiAsPromised); +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised as any); const { expect } = chai; describe('String Utils', () => { describe('encode', () => { - it('can encode to base64', async () => { + it('can encode to base64', () => { const testString = 'AAAAAAAAAA'; const encoded = StringUtils.encode(testString, 'base64'); @@ -24,7 +24,7 @@ describe('String Utils', () => { expect(encoded.byteLength).to.be.greaterThan(0); }); - it('can encode to hex', async () => { + it('can encode to hex', () => { const testString = 'AAAAAAAAAA'; const encoded = StringUtils.encode(testString, 'hex'); @@ -35,14 +35,14 @@ describe('String Utils', () => { expect(encoded.byteLength).to.be.greaterThan(0); }); - it('wont encode invalid hex', async () => { + it('wont encode invalid hex', () => { const testString = 'ZZZZZZZZZZ'; const encoded = StringUtils.encode(testString, 'hex'); expect(encoded.byteLength).to.equal(0); }); - it('can encode to binary', async () => { + it('can encode to binary', () => { const testString = 'AAAAAAAAAA'; const encoded = StringUtils.encode(testString, 'binary'); @@ -53,7 +53,7 @@ describe('String Utils', () => { expect(encoded.byteLength).to.be.greaterThan(0); }); - it('can encode to utf8', async () => { + it('can encode to utf8', () => { const testString = 'AAAAAAAAAA'; const encoded = StringUtils.encode(testString, 'binary'); @@ -64,7 +64,7 @@ describe('String Utils', () => { expect(encoded.byteLength).to.be.greaterThan(0); }); - it('can encode empty string', async () => { + it('can encode empty string', () => { const testString = ''; expect(testString).to.have.length(0); @@ -81,7 +81,7 @@ describe('String Utils', () => { }); }); - it('can encode huge string', async () => { + it('can encode huge string', () => { const stringSize = Math.pow(2, 16); const testString = Array(stringSize) .fill('0') @@ -100,7 +100,7 @@ describe('String Utils', () => { }); }); - it("won't encode illegal string length in hex", async () => { + it("won't encode illegal string length in hex", () => { const testString = 'A'; const encode = () => StringUtils.encode(testString, 'hex'); @@ -109,7 +109,7 @@ describe('String Utils', () => { expect(encode).to.throw('Illegal str: Length not a multiple of 2'); }); - it('can encode obscure string', async () => { + it('can encode obscure string', () => { const testString = '↓←¶ᶑᵶ⅑⏕→⅓‎ᵹ⅙ᵰᶎ⅔⅗↔‌ᶈ⅞⸜ᶊᵴᶉ↉¥ᶖᶋᶃᶓ⏦ᵾᶂᶆ↕⸝ᶔᶐ⏔£⏙⅐⅒ᶌ⁁ᶘᶄᶒᶸ⅘‏⅚⅛ᶙᶇᶕᶀ↑ᵿ⏠ᶍᵯ⏖⏗⅜ᶚᶏ⁊‍ᶁᶗᵽᵼ⅝⏘⅖⅕⏡'; @@ -128,7 +128,7 @@ describe('String Utils', () => { }); describe('decode', () => { - it('can decode empty buffer', async () => { + it('can decode empty buffer', () => { const buffer = new ByteBuffer(0); const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array; @@ -143,7 +143,7 @@ describe('String Utils', () => { }); }); - it('can decode huge buffer', async () => { + it('can decode huge buffer', () => { const bytes = Math.pow(2, 16); const bufferString = Array(bytes) .fill('A') @@ -162,7 +162,7 @@ describe('String Utils', () => { }); }); - it('can decode from ByteBuffer', async () => { + it('can decode from ByteBuffer', () => { const buffer = ByteBuffer.fromUTF8('AAAAAAAAAA'); const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array; @@ -177,7 +177,7 @@ describe('String Utils', () => { }); }); - it('can decode from Buffer', async () => { + it('can decode from Buffer', () => { const arrayBuffer = new ArrayBuffer(10); const buffer = Buffer.from(arrayBuffer); buffer.writeUInt8(0, 0); @@ -194,7 +194,7 @@ describe('String Utils', () => { }); }); - it('can decode from ArrayBuffer', async () => { + it('can decode from ArrayBuffer', () => { const buffer = new ArrayBuffer(10); const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array; @@ -209,7 +209,7 @@ describe('String Utils', () => { }); }); - it('can decode from Uint8Array', async () => { + it('can decode from Uint8Array', () => { const buffer = new Uint8Array(10); const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array; diff --git a/ts/test/session/unit/utils/SyncUtils_test.ts b/ts/test/session/unit/utils/SyncUtils_test.ts index d3c951775..a5594b807 100644 --- a/ts/test/session/unit/utils/SyncUtils_test.ts +++ b/ts/test/session/unit/utils/SyncUtils_test.ts @@ -1,15 +1,10 @@ +// tslint:disable: no-implicit-dependencies import chai from 'chai'; import * as sinon from 'sinon'; -import { ConversationController } from '../../../../session/conversations'; -import * as MessageUtils from '../../../../session/utils/Messages'; -import { syncConfigurationIfNeeded } from '../../../../session/utils/syncUtils'; -import { TestUtils } from '../../../test-utils'; import { restoreStubs } from '../../../test-utils/utils'; -// tslint:disable-next-line: no-require-imports no-var-requires -const chaiAsPromised = require('chai-as-promised'); -chai.use(chaiAsPromised); -const { expect } = chai; +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised as any); describe('SyncUtils', () => { const sandbox = sinon.createSandbox(); @@ -20,7 +15,7 @@ describe('SyncUtils', () => { }); describe('syncConfigurationIfNeeded', () => { - it('sync if last sync undefined', async () => { + it('sync if last sync undefined', () => { // TestUtils.stubData('getItemById').resolves(undefined); // sandbox.stub(ConversationController.getInstance(), 'getConversations').returns([]); // const getCurrentConfigurationMessageSpy = sandbox.spy(MessageUtils, 'getCurrentConfigurationMessage'); diff --git a/ts/test/tslint.json b/ts/test/tslint.json index d18bab561..ebe01b7f1 100644 --- a/ts/test/tslint.json +++ b/ts/test/tslint.json @@ -2,15 +2,10 @@ "defaultSeverity": "error", "extends": ["../../tslint.json"], "rules": { - // To allow the use of devDependencies here "no-implicit-dependencies": false, - - // All tests use arrow functions, and they can be long "max-func-body-length": false, - "no-unused-expression": false, "no-unused-variable": false, - "await-promise": [true, "PromiseLike"], "no-floating-promises": [true, "PromiseLike"] } diff --git a/ts/test/util/blockedNumberController_test.ts b/ts/test/util/blockedNumberController_test.ts index 83a7302ba..f4d3dee3f 100644 --- a/ts/test/util/blockedNumberController_test.ts +++ b/ts/test/util/blockedNumberController_test.ts @@ -1,3 +1,5 @@ +// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression + import { expect } from 'chai'; import * as sinon from 'sinon'; import { BlockedNumberController } from '../../util/blockedNumberController'; @@ -35,7 +37,7 @@ describe('BlockedNumberController', () => { TestUtils.restoreStubs(); }); - describe('load', async () => { + describe('load', () => { it('should load data from the database', async () => { const normal = TestUtils.generateFakePubKey(); const group = TestUtils.generateFakePubKey(); @@ -62,7 +64,7 @@ describe('BlockedNumberController', () => { }); }); - describe('block', async () => { + describe('block', () => { it('should block the user', async () => { const other = TestUtils.generateFakePubKey(); @@ -76,7 +78,7 @@ describe('BlockedNumberController', () => { }); }); - describe('unblock', async () => { + describe('unblock', () => { it('should unblock the user', async () => { const primary = TestUtils.generateFakePubKey(); memoryDB.blocked = [primary.key]; @@ -103,7 +105,7 @@ describe('BlockedNumberController', () => { }); }); - describe('blockGroup', async () => { + describe('blockGroup', () => { it('should block a group', async () => { const group = TestUtils.generateFakePubKey(); @@ -118,7 +120,7 @@ describe('BlockedNumberController', () => { }); }); - describe('unblockGroup', async () => { + describe('unblockGroup', () => { it('should unblock a group', async () => { const group = TestUtils.generateFakePubKey(); const another = TestUtils.generateFakePubKey(); @@ -134,7 +136,7 @@ describe('BlockedNumberController', () => { }); }); - describe('isBlocked', async () => { + describe('isBlocked', () => { it('should return true if number is blocked', async () => { const pubKey = TestUtils.generateFakePubKey(); const groupPubKey = TestUtils.generateFakePubKey(); @@ -198,7 +200,7 @@ describe('BlockedNumberController', () => { }); }); - describe('isGroupBlocked', async () => { + describe('isGroupBlocked', () => { it('should return true if group is blocked', async () => { const pubKey = TestUtils.generateFakePubKey(); const groupPubKey = TestUtils.generateFakePubKey(); diff --git a/tslint.json b/tslint.json index 70bd8cdd7..9b974cd23 100644 --- a/tslint.json +++ b/tslint.json @@ -7,40 +7,31 @@ "align": false, "newline-per-chained-call": false, "array-type": [true, "generic"], - // Preferred by Prettier: "arrow-parens": [true, "ban-single-arg-parens"], - "import-spacing": false, "indent": [true, "spaces", 2], "interface-name": [true, "never-prefix"], - // Allows us to write inline `style`s. Revisit when we have a more sophisticated // CSS-in-JS solution: "jsx-no-multiline-js": false, - // We'll make tradeoffs where appropriate "jsx-no-lambda": false, "react-this-binding-issue": false, - "linebreak-style": [true, "LF"], - // Prettier handles this for us "max-line-length": false, - "mocha-avoid-only": true, // Disabled until we can allow dynamically generated tests: // https://github.com/Microsoft/tslint-microsoft-contrib/issues/85#issuecomment-371749352 "mocha-no-side-effect-code": false, "mocha-unneeded-done": true, - // We always want 'as Type' "no-angle-bracket-type-assertion": true, - "no-consecutive-blank-lines": [true, 2], "object-literal-key-quotes": [true, "as-needed"], "object-literal-sort-keys": false, - + "no-async-without-await": true, // Ignore import sources order until we can specify that we want ordering // based on import name vs module name: "ordered-imports": [ @@ -50,7 +41,6 @@ "named-imports-order": "case-insensitive" } ], - "quotemark": [ true, "single", @@ -58,10 +48,8 @@ "avoid-template", "avoid-escape" ], - // Preferred by Prettier: "semicolon": [true, "always", "ignore-bound-class-methods"], - // Preferred by Prettier: "trailing-comma": [ true, @@ -76,11 +64,8 @@ "esSpecCompliant": true } ], - // Disabling a large set of Microsoft-recommended rules - // Modifying: - // React components and namespaces are Pascal case "variable-name": [ true, @@ -88,7 +73,6 @@ "allow-leading-underscore", "allow-pascal-case" ], - "function-name": [ true, { @@ -99,12 +83,9 @@ "static-method-regex": "^[a-zA-Z][\\w\\d]+$" } ], - // Adding select dev dependencies here for now, may turn on all in the future "no-implicit-dependencies": [true, ["dashdash", "electron"]], - // Maybe will turn on: - // We're not trying to be comprehensive with JSDoc right now. We have the style guide. "completed-docs": false, // Today we have files with a single named export which isn't the filename. Eventually. @@ -121,9 +102,7 @@ "no-unsafe-any": false, // Not everything needs to be typed right now "typedef": false, - // Probably won't turn on: - "possible-timing-attack": false, // We use null "no-null-keyword": false,