add a tslint rule to forbid use of async without await

This commit is contained in:
Audric Ackermann 2021-02-09 17:00:54 +11:00
parent 36fab86d30
commit ed84760f0e
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4
25 changed files with 133 additions and 169 deletions

View File

@ -131,8 +131,8 @@ export class RegistrationTabs extends React.Component<any, State> {
} }
public componentDidMount() { public componentDidMount() {
this.generateMnemonicAndKeyPair().ignore(); void this.generateMnemonicAndKeyPair();
this.resetRegistration().ignore(); void this.resetRegistration();
} }
public render() { public render() {
@ -345,7 +345,7 @@ export class RegistrationTabs extends React.Component<any, State> {
<SessionButton <SessionButton
onClick={() => { onClick={() => {
if (signUpMode === SignUpMode.Default) { if (signUpMode === SignUpMode.Default) {
this.onSignUpGenerateSessionIDClick().ignore(); this.onSignUpGenerateSessionIDClick();
} else { } else {
this.onSignUpGetStartedClick(); this.onSignUpGetStartedClick();
} }
@ -357,7 +357,7 @@ export class RegistrationTabs extends React.Component<any, State> {
); );
} }
private async onSignUpGenerateSessionIDClick() { private onSignUpGenerateSessionIDClick() {
this.setState( this.setState(
{ {
signUpMode: SignUpMode.SessionIDShown, signUpMode: SignUpMode.SessionIDShown,
@ -375,7 +375,7 @@ export class RegistrationTabs extends React.Component<any, State> {
} }
private onCompleteSignUpClick() { private onCompleteSignUpClick() {
this.register('english').ignore(); void this.register('english');
} }
private renderSignIn() { private renderSignIn() {
@ -541,7 +541,7 @@ export class RegistrationTabs extends React.Component<any, State> {
private handleContinueYourSessionClick() { private handleContinueYourSessionClick() {
if (this.state.signInMode === SignInMode.UsingRecoveryPhrase) { if (this.state.signInMode === SignInMode.UsingRecoveryPhrase) {
this.register('english').ignore(); void this.register('english');
} }
} }

View File

@ -50,8 +50,8 @@ class SessionSeedModalInner extends React.Component<Props, State> {
public render() { public render() {
const i18n = window.i18n; const i18n = window.i18n;
this.checkHasPassword(); void this.checkHasPassword();
this.getRecoveryPhrase().ignore(); void this.getRecoveryPhrase();
const { onClose } = this.props; const { onClose } = this.props;
const { hasPassword, passwordValid } = this.state; const { hasPassword, passwordValid } = this.state;

View File

@ -520,7 +520,7 @@ export class SessionCompositionBox extends React.Component<Props, State> {
} }
if (firstLink !== this.state.stagedLinkPreview?.url) { if (firstLink !== this.state.stagedLinkPreview?.url) {
// trigger fetching of link preview data and image // 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 // if the fetch did not start yet, just don't show anything
@ -553,7 +553,7 @@ export class SessionCompositionBox extends React.Component<Props, State> {
return <></>; return <></>;
} }
private async fetchLinkPreview(firstLink: string) { private fetchLinkPreview(firstLink: string) {
// mark the link preview as loading, no data are set yet // mark the link preview as loading, no data are set yet
this.setState({ this.setState({
stagedLinkPreview: { stagedLinkPreview: {

View File

@ -824,7 +824,7 @@ export class SessionConversation extends React.Component<Props, State> {
} }
} }
private async showMessageDetails(messageProps: any) { private showMessageDetails(messageProps: any) {
messageProps.onDeleteMessage = async (id: string) => { messageProps.onDeleteMessage = async (id: string) => {
await this.deleteMessagesById([id], false); await this.deleteMessagesById([id], false);
this.setState({ messageDetailShowProps: undefined }); this.setState({ messageDetailShowProps: undefined });

View File

@ -41,7 +41,7 @@ interface Props {
count: number; count: number;
}) => void; }) => void;
replyToMessage: (messageId: number) => Promise<void>; replyToMessage: (messageId: number) => Promise<void>;
showMessageDetails: (messageProps: any) => Promise<void>; showMessageDetails: (messageProps: any) => void;
onClickAttachment: (attachment: any, message: any) => void; onClickAttachment: (attachment: any, message: any) => void;
onDownloadAttachment: ({ attachment }: { attachment: any }) => void; onDownloadAttachment: ({ attachment }: { attachment: any }) => void;
onDeleteSelectedMessages: () => Promise<void>; onDeleteSelectedMessages: () => Promise<void>;
@ -326,7 +326,7 @@ export class SessionMessagesList extends React.Component<Props, State> {
messageProps.onReply = this.props.replyToMessage; messageProps.onReply = this.props.replyToMessage;
messageProps.onShowDetail = async () => { messageProps.onShowDetail = async () => {
const messageDetailsProps = await message.getPropsForMessageDetail(); const messageDetailsProps = await message.getPropsForMessageDetail();
void this.props.showMessageDetails(messageDetailsProps); this.props.showMessageDetails(messageDetailsProps);
}; };
messageProps.onClickAttachment = (attachment: AttachmentType) => { messageProps.onClickAttachment = (attachment: AttachmentType) => {

View File

@ -122,9 +122,9 @@ class SessionRecordingInner extends React.Component<Props, State> {
}; };
} }
public async componentWillMount() { public componentWillMount() {
// This turns on the microphone on the system. Later we need to turn it off. // This turns on the microphone on the system. Later we need to turn it off.
await this.initiateRecordingStream(); this.initiateRecordingStream();
} }
public componentDidMount() { public componentDidMount() {
@ -309,7 +309,7 @@ class SessionRecordingInner extends React.Component<Props, State> {
} }
} }
private async stopRecording() { private stopRecording() {
this.setState({ this.setState({
isRecording: false, isRecording: false,
isPaused: true, isPaused: true,
@ -436,7 +436,7 @@ class SessionRecordingInner extends React.Component<Props, State> {
this.props.sendVoiceMessage(audioBlob); this.props.sendVoiceMessage(audioBlob);
} }
private async initiateRecordingStream() { private initiateRecordingStream() {
navigator.getUserMedia( navigator.getUserMedia(
{ audio: true }, { audio: true },
this.onRecordingStream, this.onRecordingStream,
@ -462,7 +462,7 @@ class SessionRecordingInner extends React.Component<Props, State> {
streamParams.stream.getTracks().forEach((track: any) => track.stop); streamParams.stream.getTracks().forEach((track: any) => track.stop);
// Stop recording // Stop recording
await this.stopRecording(); this.stopRecording();
} }
private async onRecordingStream(stream: any) { private async onRecordingStream(stream: any) {

View File

@ -69,23 +69,23 @@ class SessionRightPanel extends React.Component<Props, State> {
} }
public componentWillMount() { public componentWillMount() {
this.getMediaGalleryProps() void this.getMediaGalleryProps().then(
.then(({ documents, media, onItemClick }) => { ({ documents, media, onItemClick }) => {
this.setState({ this.setState({
documents, documents,
media, media,
onItemClick, onItemClick,
}); });
}) }
.ignore(); );
} }
public componentDidUpdate() { public componentDidUpdate() {
const mediaScanInterval = 1000; const mediaScanInterval = 1000;
setTimeout(() => { setTimeout(() => {
this.getMediaGalleryProps() void this.getMediaGalleryProps().then(
.then(({ documents, media, onItemClick }) => { ({ documents, media, onItemClick }) => {
const { documents: oldDocs, media: oldMedias } = this.state; const { documents: oldDocs, media: oldMedias } = this.state;
if ( if (
oldDocs.length !== documents.length || oldDocs.length !== documents.length ||
@ -97,8 +97,8 @@ class SessionRightPanel extends React.Component<Props, State> {
onItemClick, onItemClick,
}); });
} }
}) }
.ignore(); );
}, mediaScanInterval); }, mediaScanInterval);
} }
@ -193,7 +193,7 @@ class SessionRightPanel extends React.Component<Props, State> {
} }
); );
const saveAttachment = async ({ attachment, message }: any = {}) => { const saveAttachment = ({ attachment, message }: any = {}) => {
const timestamp = message.received_at; const timestamp = message.received_at;
save({ save({
attachment, attachment,
@ -203,10 +203,10 @@ class SessionRightPanel extends React.Component<Props, State> {
}); });
}; };
const onItemClick = async ({ message, attachment, type }: any) => { const onItemClick = ({ message, attachment, type }: any) => {
switch (type) { switch (type) {
case 'documents': { case 'documents': {
saveAttachment({ message, attachment }).ignore(); saveAttachment({ message, attachment });
break; break;
} }

View File

@ -422,7 +422,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
if (!registeredMessage || !registeredMessage.message) { if (!registeredMessage || !registeredMessage.message) {
return null; return null;
} }
const model = registeredMessage.message as MessageModel; const model = registeredMessage.message;
await model.setIsPublic(true); await model.setIsPublic(true);
await model.setServerId(serverId); await model.setServerId(serverId);
await model.setServerTimestamp(serverTimestamp); await model.setServerTimestamp(serverTimestamp);
@ -1298,7 +1298,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
} }
} }
public async setSubscriberCount(count: number) { 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 // Not sure if we care about updating the database
} }
public async setGroupNameAndAvatar(name: any, avatarPath: any) { public async setGroupNameAndAvatar(name: any, avatarPath: any) {

View File

@ -115,7 +115,7 @@ async function copyFromQuotedMessage(
window.log.info( window.log.info(
`Looking for the message id : ${id}, attempt: ${attemptCount + 1}` `Looking for the message id : ${id}, attempt: ${attemptCount + 1}`
); );
copyFromQuotedMessage(msg, quote, attemptCount + 1).ignore(); void copyFromQuotedMessage(msg, quote, attemptCount + 1);
}, attemptCount * attemptCount * 500); }, attemptCount * attemptCount * 500);
} else { } else {
window.log.warn( window.log.warn(

View File

@ -52,7 +52,7 @@ class EnvelopeQueue {
// Last pending promise // Last pending promise
private pending: Promise<any> = Promise.resolve(); private pending: Promise<any> = Promise.resolve();
public async add(task: any): Promise<any> { public add(task: any): void {
this.count += 1; this.count += 1;
const promise = this.pending.then(task, task); const promise = this.pending.then(task, task);
this.pending = promise; this.pending = promise;
@ -85,16 +85,16 @@ function queueEnvelope(envelope: EnvelopePlus) {
`queueEnvelope ${id}` `queueEnvelope ${id}`
); );
const promise = envelopeQueue.add(taskWithTimeout); try {
envelopeQueue.add(taskWithTimeout);
promise.catch((error: any) => { } catch (error) {
window.log.error( window.log.error(
'queueEnvelope error handling envelope', 'queueEnvelope error handling envelope',
id, id,
':', ':',
error && error.stack ? error.stack : error error && error.stack ? error.stack : error
); );
}); }
} }
async function handleRequestDetail( async function handleRequestDetail(
@ -154,10 +154,7 @@ async function handleRequestDetail(
} }
} }
export async function handleRequest( export function handleRequest(body: any, options: ReqOptions): void {
body: any,
options: ReqOptions
): Promise<void> {
// tslint:disable-next-line no-promise-as-boolean // tslint:disable-next-line no-promise-as-boolean
const lastPromise = _.last(incomingMessagePromises) || Promise.resolve(); const lastPromise = _.last(incomingMessagePromises) || Promise.resolve();
@ -210,7 +207,7 @@ async function queueCached(item: any) {
if (decrypted) { if (decrypted) {
const payloadPlaintext = StringUtils.encode(decrypted, 'base64'); const payloadPlaintext = StringUtils.encode(decrypted, 'base64');
await queueDecryptedEnvelope(envelope, payloadPlaintext); queueDecryptedEnvelope(envelope, payloadPlaintext);
} else { } else {
queueEnvelope(envelope); 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); const id = getEnvelopeId(envelope);
window.log.info('queueing decrypted envelope', id); window.log.info('queueing decrypted envelope', id);
@ -245,14 +242,14 @@ async function queueDecryptedEnvelope(envelope: any, plaintext: ArrayBuffer) {
task, task,
`queueEncryptedEnvelope ${id}` `queueEncryptedEnvelope ${id}`
); );
const promise = envelopeQueue.add(taskWithTimeout); try {
envelopeQueue.add(taskWithTimeout);
return promise.catch(error => { } catch (error) {
window.log.error( window.log.error(
`queueDecryptedEnvelope error handling envelope ${id}:`, `queueDecryptedEnvelope error handling envelope ${id}:`,
error && error.stack ? error.stack : error error && error.stack ? error.stack : error
); );
}); }
} }
async function handleDecryptedEnvelope( async function handleDecryptedEnvelope(

View File

@ -310,9 +310,7 @@ export async function updateOrCreateClosedGroup(details: GroupInfo) {
} }
export async function leaveClosedGroup(groupId: string) { export async function leaveClosedGroup(groupId: string) {
const convo = ConversationController.getInstance().get( const convo = ConversationController.getInstance().get(groupId);
groupId
) as ConversationModel;
if (!convo) { if (!convo) {
window.log.error('Cannot leave non-existing group'); window.log.error('Cannot leave non-existing group');
@ -334,7 +332,9 @@ export async function leaveClosedGroup(groupId: string) {
} else { } else {
// otherwise, just the exclude ourself from the members and trigger an update with this // otherwise, just the exclude ourself from the members and trigger an update with this
convo.set({ left: true }); 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') || []; admins = convo.get('groupAdmins') || [];
} }
convo.set({ members }); convo.set({ members });

View File

@ -52,7 +52,7 @@ export class SwarmPolling {
this.lastHashes = {}; this.lastHashes = {};
} }
public async start(): Promise<void> { public start(): void {
this.loadGroupIds(); this.loadGroupIds();
void this.pollForAllKeys(); void this.pollForAllKeys();
} }

View File

@ -1,6 +1,6 @@
// tslint:disable: no-implicit-dependencies // tslint:disable: no-implicit-dependencies
import { Application, SpectronClient } from 'spectron'; import { Application } from 'spectron';
import path from 'path'; import path from 'path';
import url from 'url'; import url from 'url';
import http from 'http'; import http from 'http';
@ -73,7 +73,7 @@ export class Common {
} }
public static async closeToast(app: Application) { 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 // a wrapper to work around electron/spectron bug
@ -219,7 +219,7 @@ export class Common {
env?: string; env?: string;
}) { }) {
const app = await Common.startAndAssureCleanedApp(env); const app = await Common.startAndAssureCleanedApp(env);
await Common.startStubSnodeServer(); Common.startStubSnodeServer();
if (recoveryPhrase && displayName) { if (recoveryPhrase && displayName) {
await Common.restoreFromRecoveryPhrase(app, recoveryPhrase, displayName); await Common.restoreFromRecoveryPhrase(app, recoveryPhrase, displayName);
@ -562,7 +562,7 @@ export class Common {
return `Test message from integration tests ${Date.now()}`; return `Test message from integration tests ${Date.now()}`;
} }
public static async startStubSnodeServer() { public static startStubSnodeServer() {
if (!Common.stubSnode) { if (!Common.stubSnode) {
Common.messages = {}; Common.messages = {};
Common.stubSnode = http.createServer((request: any, response: any) => { Common.stubSnode = http.createServer((request: any, response: any) => {
@ -684,7 +684,7 @@ export class Common {
public static async stopStubSnodeServer() { public static async stopStubSnodeServer() {
if (Common.stubSnode) { if (Common.stubSnode) {
Common.stubSnode.close(); await Common.stubSnode.close();
Common.stubSnode = null; Common.stubSnode = null;
} }
} }
@ -695,7 +695,7 @@ export class Common {
* @param str the string to search (not regex) * @param str the string to search (not regex)
* Note: getRenderProcessLogs() clears the app logs each calls. * Note: getRenderProcessLogs() clears the app logs each calls.
*/ */
public static async logsContains( public static logsContains(
renderLogs: Array<{ message: string }>, renderLogs: Array<{ message: string }>,
str: string, str: string,
count?: number count?: number

View File

@ -165,9 +165,9 @@ describe('MessageEncrypter', () => {
.to.deep.equal(SignalService.Envelope.Type.UNIDENTIFIED_SENDER); .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); const data = crypto.randomBytes(10);
await expect( expect(
MessageEncrypter.encrypt( MessageEncrypter.encrypt(
TestUtils.generateFakePubKey(), TestUtils.generateFakePubKey(),
data, data,
@ -182,7 +182,7 @@ describe('MessageEncrypter', () => {
describe('Session Protocol', () => { describe('Session Protocol', () => {
let sandboxSessionProtocol: sinon.SinonSandbox; let sandboxSessionProtocol: sinon.SinonSandbox;
beforeEach(async () => { beforeEach(() => {
sandboxSessionProtocol = sinon.createSandbox(); sandboxSessionProtocol = sinon.createSandbox();
sandboxSessionProtocol sandboxSessionProtocol

View File

@ -1,22 +1,11 @@
// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
import chai from 'chai'; import chai from 'chai';
import * as sinon from 'sinon';
import _ from 'lodash'; import _ from 'lodash';
import { describe } from 'mocha'; import { describe } from 'mocha';
import { GroupUtils, PromiseUtils, UserUtils } from '../../../../session/utils'; import chaiAsPromised from 'chai-as-promised';
import { TestUtils } from '../../../../test/test-utils'; chai.use(chaiAsPromised as any);
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;
// tslint:disable-next-line: max-func-body-length // tslint:disable-next-line: max-func-body-length
describe('ClosedGroupUpdates', () => { describe('ClosedGroupUpdates', () => {

View File

@ -1,3 +1,5 @@
// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
import chai from 'chai'; import chai from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import _ from 'lodash'; import _ from 'lodash';
@ -15,9 +17,8 @@ import { MessageSender } from '../../../../session/sending';
import { PendingMessageCacheStub } from '../../../test-utils/stubs'; import { PendingMessageCacheStub } from '../../../test-utils/stubs';
import { ClosedGroupMessage } from '../../../../session/messages/outgoing/content/data/group/ClosedGroupMessage'; import { ClosedGroupMessage } from '../../../../session/messages/outgoing/content/data/group/ClosedGroupMessage';
// tslint:disable-next-line: no-require-imports no-var-requires import chaiAsPromised from 'chai-as-promised';
const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised as any);
chai.use(chaiAsPromised);
const { expect } = chai; const { expect } = chai;
@ -35,7 +36,7 @@ describe('MessageQueue', () => {
// Message Sender Stubs // Message Sender Stubs
let sendStub: sinon.SinonStub<[RawMessage, (number | undefined)?]>; let sendStub: sinon.SinonStub<[RawMessage, (number | undefined)?]>;
beforeEach(async () => { beforeEach(() => {
// Utils Stubs // Utils Stubs
sandbox.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(ourNumber); sandbox.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(ourNumber);
@ -65,7 +66,8 @@ describe('MessageQueue', () => {
messageQueueStub.events.once('sendSuccess', done); messageQueueStub.events.once('sendSuccess', done);
}); });
await messageQueueStub.processPending(device); 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 () => { it('should remove message from cache', async () => {
@ -88,7 +90,7 @@ describe('MessageQueue', () => {
const messages = await pendingMessageCache.getForDevice(device); const messages = await pendingMessageCache.getForDevice(device);
return messages.length === 0; return messages.length === 0;
}); });
await expect(promise).to.be.fulfilled; return promise.should.be.fulfilled;
} }
}).timeout(15000); }).timeout(15000);
@ -105,7 +107,6 @@ describe('MessageQueue', () => {
}); });
await messageQueueStub.processPending(device); await messageQueueStub.processPending(device);
await expect(eventPromise).to.be.fulfilled;
const rawMessage = await eventPromise; const rawMessage = await eventPromise;
expect(rawMessage.identifier).to.equal(message.identifier); expect(rawMessage.identifier).to.equal(message.identifier);
@ -130,7 +131,6 @@ describe('MessageQueue', () => {
}); });
await messageQueueStub.processPending(device); await messageQueueStub.processPending(device);
await expect(eventPromise).to.be.fulfilled;
const [rawMessage, error] = await eventPromise; const [rawMessage, error] = await eventPromise;
expect(rawMessage.identifier).to.equal(message.identifier); expect(rawMessage.identifier).to.equal(message.identifier);
@ -166,7 +166,7 @@ describe('MessageQueue', () => {
}); });
describe('sendToGroup', () => { 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(); // const chatMessage = TestUtils.generateChatMessage();
// await expect( // await expect(
// messageQueueStub.sendToGroup(chatMessage) // messageQueueStub.sendToGroup(chatMessage)
@ -174,7 +174,7 @@ describe('MessageQueue', () => {
// Cannot happen with typescript as this function only accept group message now // 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 () => { it('can send to closed group', async () => {
const members = TestUtils.generateFakePubKeys(4).map( const members = TestUtils.generateFakePubKeys(4).map(
p => new PubKey(p.key) p => new PubKey(p.key)
@ -194,7 +194,7 @@ describe('MessageQueue', () => {
); );
}); });
describe('open groups', async () => { describe('open groups', () => {
let sendToOpenGroupStub: sinon.SinonStub< let sendToOpenGroupStub: sinon.SinonStub<
[OpenGroupMessage], [OpenGroupMessage],
Promise<{ serverId: number; serverTimestamp: number }> Promise<{ serverId: number; serverTimestamp: number }>
@ -223,7 +223,7 @@ describe('MessageQueue', () => {
}, 2000); }, 2000);
await messageQueueStub.sendToGroup(message); 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 () => { it('should emit a fail event if something went wrong', async () => {
@ -234,7 +234,7 @@ describe('MessageQueue', () => {
}, 2000); }, 2000);
await messageQueueStub.sendToGroup(message); await messageQueueStub.sendToGroup(message);
await expect(eventPromise).to.be.fulfilled; return eventPromise.should.be.fulfilled;
}); });
}); });
}); });

View File

@ -1,3 +1,4 @@
// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
import { expect } from 'chai'; import { expect } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -17,7 +18,7 @@ describe('PendingMessageCache', () => {
let data: StorageItem; let data: StorageItem;
let pendingMessageCacheStub: PendingMessageCache; let pendingMessageCacheStub: PendingMessageCache;
beforeEach(async () => { beforeEach(() => {
// Stub out methods which touch the database // Stub out methods which touch the database
const storageID = 'pendingMessages'; const storageID = 'pendingMessages';
data = { data = {

View File

@ -1,11 +1,12 @@
// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
import chai from 'chai'; import chai from 'chai';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import { JobQueue } from '../../../../session/utils/JobQueue'; import { JobQueue } from '../../../../session/utils/JobQueue';
import { TestUtils } from '../../../test-utils'; import { TestUtils } from '../../../test-utils';
// tslint:disable-next-line: no-require-imports no-var-requires import chaiAsPromised from 'chai-as-promised';
const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised as any);
chai.use(chaiAsPromised);
const { assert } = chai; const { assert } = chai;

View File

@ -17,9 +17,9 @@ import {
import { MockConversation } from '../../../test-utils/utils'; import { MockConversation } from '../../../test-utils/utils';
import { ConfigurationMessage } from '../../../../session/messages/outgoing/content/ConfigurationMessage'; import { ConfigurationMessage } from '../../../../session/messages/outgoing/content/ConfigurationMessage';
import { ConversationModel } from '../../../../models/conversation'; import { ConversationModel } from '../../../../models/conversation';
// tslint:disable-next-line: no-require-imports no-var-requires
const chaiAsPromised = require('chai-as-promised'); import chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised); chai.use(chaiAsPromised as any);
const { expect } = chai; const { expect } = chai;

View File

@ -1,11 +1,13 @@
// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
import chai from 'chai'; import chai from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { PromiseUtils } from '../../../../session/utils'; import { PromiseUtils } from '../../../../session/utils';
// tslint:disable-next-line: no-require-imports no-var-requires // tslint:disable-next-line: no-require-imports no-var-requires
const chaiAsPromised = require('chai-as-promised'); import chaiAsPromised from 'chai-as-promised';
chai.use(chaiAsPromised); chai.use(chaiAsPromised as any);
const { expect } = chai; const { expect } = chai;
@ -49,20 +51,20 @@ describe('Promise Utils', () => {
}; };
const promise = PromiseUtils.poll(task, {}); const promise = PromiseUtils.poll(task, {});
await promise;
await expect(promise).to.be.fulfilled;
expect(pollSpy.callCount).to.equal(1); expect(pollSpy.callCount).to.equal(1);
expect(completionSpy.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 // completionSpy will be called on done
const completionSpy = sandbox.spy(); const completionSpy = sandbox.spy();
const task = (_done: any) => undefined; const task = (_done: any) => undefined;
const promise = PromiseUtils.poll(task, { timeoutMs: 1 }); 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(pollSpy.callCount).to.equal(1);
expect(completionSpy.callCount).to.equal(0); expect(completionSpy.callCount).to.equal(0);
}); });
@ -83,8 +85,8 @@ describe('Promise Utils', () => {
}; };
const promise = PromiseUtils.poll(task, { timeoutMs: timeout, interval }); const promise = PromiseUtils.poll(task, { timeoutMs: timeout, interval });
await promise;
await expect(promise).to.be.fulfilled;
expect(pollSpy.callCount).to.equal(1); expect(pollSpy.callCount).to.equal(1);
expect(recurrenceSpy.callCount).to.equal(expectedRecurrences); expect(recurrenceSpy.callCount).to.equal(expectedRecurrences);
}); });
@ -103,19 +105,19 @@ describe('Promise Utils', () => {
const promise = PromiseUtils.waitForTask(task); const promise = PromiseUtils.waitForTask(task);
await expect(promise).to.be.fulfilled; await promise;
expect(waitForTaskSpy.callCount).to.equal(1); expect(waitForTaskSpy.callCount).to.equal(1);
expect(completionSpy.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 // completionSpy will be called on done
const completionSpy = sandbox.spy(); const completionSpy = sandbox.spy();
const task = async (_done: any) => undefined; const task = async (_done: any) => undefined;
const promise = PromiseUtils.waitForTask(task, 1); 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(waitForTaskSpy.callCount).to.equal(1);
expect(completionSpy.callCount).to.equal(0); expect(completionSpy.callCount).to.equal(0);
}); });
@ -125,16 +127,16 @@ describe('Promise Utils', () => {
it('can wait for check', async () => { it('can wait for check', async () => {
const check = () => true; const check = () => true;
const promise = PromiseUtils.waitUntil(check); const promise = PromiseUtils.waitUntil(check);
await promise;
await expect(promise).to.be.fulfilled;
expect(waitUntilSpy.callCount).to.equal(1); expect(waitUntilSpy.callCount).to.equal(1);
}); });
it('can timeout a check', async () => { it('can timeout a check', () => {
const check = () => false; const check = () => false;
const promise = PromiseUtils.waitUntil(check, 1); 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); expect(waitUntilSpy.callCount).to.equal(1);
}); });
}); });

View File

@ -1,3 +1,4 @@
// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
import chai from 'chai'; import chai from 'chai';
import ByteBuffer from 'bytebuffer'; import ByteBuffer from 'bytebuffer';
@ -5,15 +6,14 @@ import ByteBuffer from 'bytebuffer';
import { Encoding } from '../../../../session/utils/String'; import { Encoding } from '../../../../session/utils/String';
import { StringUtils } from '../../../../session/utils'; import { StringUtils } from '../../../../session/utils';
// tslint:disable-next-line: no-require-imports no-var-requires import chaiAsPromised from 'chai-as-promised';
const chaiAsPromised = require('chai-as-promised'); chai.use(chaiAsPromised as any);
chai.use(chaiAsPromised);
const { expect } = chai; const { expect } = chai;
describe('String Utils', () => { describe('String Utils', () => {
describe('encode', () => { describe('encode', () => {
it('can encode to base64', async () => { it('can encode to base64', () => {
const testString = 'AAAAAAAAAA'; const testString = 'AAAAAAAAAA';
const encoded = StringUtils.encode(testString, 'base64'); const encoded = StringUtils.encode(testString, 'base64');
@ -24,7 +24,7 @@ describe('String Utils', () => {
expect(encoded.byteLength).to.be.greaterThan(0); expect(encoded.byteLength).to.be.greaterThan(0);
}); });
it('can encode to hex', async () => { it('can encode to hex', () => {
const testString = 'AAAAAAAAAA'; const testString = 'AAAAAAAAAA';
const encoded = StringUtils.encode(testString, 'hex'); const encoded = StringUtils.encode(testString, 'hex');
@ -35,14 +35,14 @@ describe('String Utils', () => {
expect(encoded.byteLength).to.be.greaterThan(0); expect(encoded.byteLength).to.be.greaterThan(0);
}); });
it('wont encode invalid hex', async () => { it('wont encode invalid hex', () => {
const testString = 'ZZZZZZZZZZ'; const testString = 'ZZZZZZZZZZ';
const encoded = StringUtils.encode(testString, 'hex'); const encoded = StringUtils.encode(testString, 'hex');
expect(encoded.byteLength).to.equal(0); expect(encoded.byteLength).to.equal(0);
}); });
it('can encode to binary', async () => { it('can encode to binary', () => {
const testString = 'AAAAAAAAAA'; const testString = 'AAAAAAAAAA';
const encoded = StringUtils.encode(testString, 'binary'); const encoded = StringUtils.encode(testString, 'binary');
@ -53,7 +53,7 @@ describe('String Utils', () => {
expect(encoded.byteLength).to.be.greaterThan(0); expect(encoded.byteLength).to.be.greaterThan(0);
}); });
it('can encode to utf8', async () => { it('can encode to utf8', () => {
const testString = 'AAAAAAAAAA'; const testString = 'AAAAAAAAAA';
const encoded = StringUtils.encode(testString, 'binary'); const encoded = StringUtils.encode(testString, 'binary');
@ -64,7 +64,7 @@ describe('String Utils', () => {
expect(encoded.byteLength).to.be.greaterThan(0); expect(encoded.byteLength).to.be.greaterThan(0);
}); });
it('can encode empty string', async () => { it('can encode empty string', () => {
const testString = ''; const testString = '';
expect(testString).to.have.length(0); 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 stringSize = Math.pow(2, 16);
const testString = Array(stringSize) const testString = Array(stringSize)
.fill('0') .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 testString = 'A';
const encode = () => StringUtils.encode(testString, 'hex'); 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'); 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 = const testString =
'↓←¶ᶑᵶ⅑⏕→⅓‎ᵹ⅙ᵰᶎ⅔⅗↔‌ᶈ⅞⸜ᶊᵴᶉ↉¥ᶖᶋᶃᶓ⏦ᵾᶂᶆ↕⸝ᶔᶐ⏔£⏙⅐⅒ᶌ⁁ᶘᶄᶒᶸ⅘‏⅚⅛ᶙᶇᶕᶀ↑ᵿ⏠ᶍᵯ⏖⏗⅜ᶚᶏ⁊‍ᶁᶗᵽᵼ⅝⏘⅖⅕⏡'; '↓←¶ᶑᵶ⅑⏕→⅓‎ᵹ⅙ᵰᶎ⅔⅗↔‌ᶈ⅞⸜ᶊᵴᶉ↉¥ᶖᶋᶃᶓ⏦ᵾᶂᶆ↕⸝ᶔᶐ⏔£⏙⅐⅒ᶌ⁁ᶘᶄᶒᶸ⅘‏⅚⅛ᶙᶇᶕᶀ↑ᵿ⏠ᶍᵯ⏖⏗⅜ᶚᶏ⁊‍ᶁᶗᵽᵼ⅝⏘⅖⅕⏡';
@ -128,7 +128,7 @@ describe('String Utils', () => {
}); });
describe('decode', () => { describe('decode', () => {
it('can decode empty buffer', async () => { it('can decode empty buffer', () => {
const buffer = new ByteBuffer(0); const buffer = new ByteBuffer(0);
const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>; const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;
@ -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 bytes = Math.pow(2, 16);
const bufferString = Array(bytes) const bufferString = Array(bytes)
.fill('A') .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 buffer = ByteBuffer.fromUTF8('AAAAAAAAAA');
const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>; const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;
@ -177,7 +177,7 @@ describe('String Utils', () => {
}); });
}); });
it('can decode from Buffer', async () => { it('can decode from Buffer', () => {
const arrayBuffer = new ArrayBuffer(10); const arrayBuffer = new ArrayBuffer(10);
const buffer = Buffer.from(arrayBuffer); const buffer = Buffer.from(arrayBuffer);
buffer.writeUInt8(0, 0); 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 buffer = new ArrayBuffer(10);
const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>; const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;
@ -209,7 +209,7 @@ describe('String Utils', () => {
}); });
}); });
it('can decode from Uint8Array', async () => { it('can decode from Uint8Array', () => {
const buffer = new Uint8Array(10); const buffer = new Uint8Array(10);
const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>; const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;

View File

@ -1,15 +1,10 @@
// tslint:disable: no-implicit-dependencies
import chai from 'chai'; import chai from 'chai';
import * as sinon from 'sinon'; 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'; 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', () => { describe('SyncUtils', () => {
const sandbox = sinon.createSandbox(); const sandbox = sinon.createSandbox();
@ -20,7 +15,7 @@ describe('SyncUtils', () => {
}); });
describe('syncConfigurationIfNeeded', () => { describe('syncConfigurationIfNeeded', () => {
it('sync if last sync undefined', async () => { it('sync if last sync undefined', () => {
// TestUtils.stubData('getItemById').resolves(undefined); // TestUtils.stubData('getItemById').resolves(undefined);
// sandbox.stub(ConversationController.getInstance(), 'getConversations').returns([]); // sandbox.stub(ConversationController.getInstance(), 'getConversations').returns([]);
// const getCurrentConfigurationMessageSpy = sandbox.spy(MessageUtils, 'getCurrentConfigurationMessage'); // const getCurrentConfigurationMessageSpy = sandbox.spy(MessageUtils, 'getCurrentConfigurationMessage');

View File

@ -2,15 +2,10 @@
"defaultSeverity": "error", "defaultSeverity": "error",
"extends": ["../../tslint.json"], "extends": ["../../tslint.json"],
"rules": { "rules": {
// To allow the use of devDependencies here
"no-implicit-dependencies": false, "no-implicit-dependencies": false,
// All tests use arrow functions, and they can be long
"max-func-body-length": false, "max-func-body-length": false,
"no-unused-expression": false, "no-unused-expression": false,
"no-unused-variable": false, "no-unused-variable": false,
"await-promise": [true, "PromiseLike"], "await-promise": [true, "PromiseLike"],
"no-floating-promises": [true, "PromiseLike"] "no-floating-promises": [true, "PromiseLike"]
} }

View File

@ -1,3 +1,5 @@
// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
import { expect } from 'chai'; import { expect } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { BlockedNumberController } from '../../util/blockedNumberController'; import { BlockedNumberController } from '../../util/blockedNumberController';
@ -35,7 +37,7 @@ describe('BlockedNumberController', () => {
TestUtils.restoreStubs(); TestUtils.restoreStubs();
}); });
describe('load', async () => { describe('load', () => {
it('should load data from the database', async () => { it('should load data from the database', async () => {
const normal = TestUtils.generateFakePubKey(); const normal = TestUtils.generateFakePubKey();
const group = TestUtils.generateFakePubKey(); const group = TestUtils.generateFakePubKey();
@ -62,7 +64,7 @@ describe('BlockedNumberController', () => {
}); });
}); });
describe('block', async () => { describe('block', () => {
it('should block the user', async () => { it('should block the user', async () => {
const other = TestUtils.generateFakePubKey(); const other = TestUtils.generateFakePubKey();
@ -76,7 +78,7 @@ describe('BlockedNumberController', () => {
}); });
}); });
describe('unblock', async () => { describe('unblock', () => {
it('should unblock the user', async () => { it('should unblock the user', async () => {
const primary = TestUtils.generateFakePubKey(); const primary = TestUtils.generateFakePubKey();
memoryDB.blocked = [primary.key]; memoryDB.blocked = [primary.key];
@ -103,7 +105,7 @@ describe('BlockedNumberController', () => {
}); });
}); });
describe('blockGroup', async () => { describe('blockGroup', () => {
it('should block a group', async () => { it('should block a group', async () => {
const group = TestUtils.generateFakePubKey(); const group = TestUtils.generateFakePubKey();
@ -118,7 +120,7 @@ describe('BlockedNumberController', () => {
}); });
}); });
describe('unblockGroup', async () => { describe('unblockGroup', () => {
it('should unblock a group', async () => { it('should unblock a group', async () => {
const group = TestUtils.generateFakePubKey(); const group = TestUtils.generateFakePubKey();
const another = 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 () => { it('should return true if number is blocked', async () => {
const pubKey = TestUtils.generateFakePubKey(); const pubKey = TestUtils.generateFakePubKey();
const groupPubKey = 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 () => { it('should return true if group is blocked', async () => {
const pubKey = TestUtils.generateFakePubKey(); const pubKey = TestUtils.generateFakePubKey();
const groupPubKey = TestUtils.generateFakePubKey(); const groupPubKey = TestUtils.generateFakePubKey();

View File

@ -7,40 +7,31 @@
"align": false, "align": false,
"newline-per-chained-call": false, "newline-per-chained-call": false,
"array-type": [true, "generic"], "array-type": [true, "generic"],
// Preferred by Prettier: // Preferred by Prettier:
"arrow-parens": [true, "ban-single-arg-parens"], "arrow-parens": [true, "ban-single-arg-parens"],
"import-spacing": false, "import-spacing": false,
"indent": [true, "spaces", 2], "indent": [true, "spaces", 2],
"interface-name": [true, "never-prefix"], "interface-name": [true, "never-prefix"],
// Allows us to write inline `style`s. Revisit when we have a more sophisticated // Allows us to write inline `style`s. Revisit when we have a more sophisticated
// CSS-in-JS solution: // CSS-in-JS solution:
"jsx-no-multiline-js": false, "jsx-no-multiline-js": false,
// We'll make tradeoffs where appropriate // We'll make tradeoffs where appropriate
"jsx-no-lambda": false, "jsx-no-lambda": false,
"react-this-binding-issue": false, "react-this-binding-issue": false,
"linebreak-style": [true, "LF"], "linebreak-style": [true, "LF"],
// Prettier handles this for us // Prettier handles this for us
"max-line-length": false, "max-line-length": false,
"mocha-avoid-only": true, "mocha-avoid-only": true,
// Disabled until we can allow dynamically generated tests: // Disabled until we can allow dynamically generated tests:
// https://github.com/Microsoft/tslint-microsoft-contrib/issues/85#issuecomment-371749352 // https://github.com/Microsoft/tslint-microsoft-contrib/issues/85#issuecomment-371749352
"mocha-no-side-effect-code": false, "mocha-no-side-effect-code": false,
"mocha-unneeded-done": true, "mocha-unneeded-done": true,
// We always want 'as Type' // We always want 'as Type'
"no-angle-bracket-type-assertion": true, "no-angle-bracket-type-assertion": true,
"no-consecutive-blank-lines": [true, 2], "no-consecutive-blank-lines": [true, 2],
"object-literal-key-quotes": [true, "as-needed"], "object-literal-key-quotes": [true, "as-needed"],
"object-literal-sort-keys": false, "object-literal-sort-keys": false,
"no-async-without-await": true,
// Ignore import sources order until we can specify that we want ordering // Ignore import sources order until we can specify that we want ordering
// based on import name vs module name: // based on import name vs module name:
"ordered-imports": [ "ordered-imports": [
@ -50,7 +41,6 @@
"named-imports-order": "case-insensitive" "named-imports-order": "case-insensitive"
} }
], ],
"quotemark": [ "quotemark": [
true, true,
"single", "single",
@ -58,10 +48,8 @@
"avoid-template", "avoid-template",
"avoid-escape" "avoid-escape"
], ],
// Preferred by Prettier: // Preferred by Prettier:
"semicolon": [true, "always", "ignore-bound-class-methods"], "semicolon": [true, "always", "ignore-bound-class-methods"],
// Preferred by Prettier: // Preferred by Prettier:
"trailing-comma": [ "trailing-comma": [
true, true,
@ -76,11 +64,8 @@
"esSpecCompliant": true "esSpecCompliant": true
} }
], ],
// Disabling a large set of Microsoft-recommended rules // Disabling a large set of Microsoft-recommended rules
// Modifying: // Modifying:
// React components and namespaces are Pascal case // React components and namespaces are Pascal case
"variable-name": [ "variable-name": [
true, true,
@ -88,7 +73,6 @@
"allow-leading-underscore", "allow-leading-underscore",
"allow-pascal-case" "allow-pascal-case"
], ],
"function-name": [ "function-name": [
true, true,
{ {
@ -99,12 +83,9 @@
"static-method-regex": "^[a-zA-Z][\\w\\d]+$" "static-method-regex": "^[a-zA-Z][\\w\\d]+$"
} }
], ],
// Adding select dev dependencies here for now, may turn on all in the future // Adding select dev dependencies here for now, may turn on all in the future
"no-implicit-dependencies": [true, ["dashdash", "electron"]], "no-implicit-dependencies": [true, ["dashdash", "electron"]],
// Maybe will turn on: // Maybe will turn on:
// We're not trying to be comprehensive with JSDoc right now. We have the style guide. // We're not trying to be comprehensive with JSDoc right now. We have the style guide.
"completed-docs": false, "completed-docs": false,
// Today we have files with a single named export which isn't the filename. Eventually. // Today we have files with a single named export which isn't the filename. Eventually.
@ -121,9 +102,7 @@
"no-unsafe-any": false, "no-unsafe-any": false,
// Not everything needs to be typed right now // Not everything needs to be typed right now
"typedef": false, "typedef": false,
// Probably won't turn on: // Probably won't turn on:
"possible-timing-attack": false, "possible-timing-attack": false,
// We use null // We use null
"no-null-keyword": false, "no-null-keyword": false,