From 75513d08de4ff6059d04b55c05ee99659b0c5692 Mon Sep 17 00:00:00 2001 From: Kerry Date: Thu, 28 Jul 2022 08:09:21 +0200 Subject: [PATCH] test typescriptification - misc (#2547) * renamed: spec/unit/login.spec.js -> spec/unit/login.spec.ts * type test client * renamed: spec/unit/interactive-auth.spec.js -> spec/unit/interactive-auth.spec.ts * fix ts issues in interactive-auth.spec * renamed: spec/unit/filter.spec.js -> spec/unit/filter.spec.ts * fix ts in filter.spec * renamed: spec/unit/event.spec.js -> spec/unit/event.spec.ts * ts in event.spec * renamed: spec/unit/pushprocessor.spec.js -> spec/unit/pushprocessor.spec.ts * fix ts in pushprocessor.spec * fix ts in realtime-callbacks.spec * renamed: spec/unit/content-repo.spec.js -> spec/unit/content-repo.spec.ts * fix signature for getHttpUriForMxc * pr fixes --- ...tent-repo.spec.js => content-repo.spec.ts} | 50 +++++++------- spec/unit/{event.spec.js => event.spec.ts} | 41 +++++------- spec/unit/{filter.spec.js => filter.spec.ts} | 6 +- ...-auth.spec.js => interactive-auth.spec.ts} | 66 ++++++++++--------- spec/unit/{login.spec.js => login.spec.ts} | 2 +- ...rocessor.spec.js => pushprocessor.spec.ts} | 8 +-- ...cks.spec.js => realtime-callbacks.spec.ts} | 20 +++--- src/content-repo.ts | 6 +- 8 files changed, 96 insertions(+), 103 deletions(-) rename spec/unit/{content-repo.spec.js => content-repo.spec.ts} (51%) rename spec/unit/{event.spec.js => event.spec.ts} (57%) rename spec/unit/{filter.spec.js => filter.spec.ts} (89%) rename spec/unit/{interactive-auth.spec.js => interactive-auth.spec.ts} (84%) rename spec/unit/{login.spec.js => login.spec.ts} (96%) rename spec/unit/{pushprocessor.spec.js => pushprocessor.spec.ts} (98%) rename spec/unit/{realtime-callbacks.spec.js => realtime-callbacks.spec.ts} (93%) diff --git a/spec/unit/content-repo.spec.js b/spec/unit/content-repo.spec.ts similarity index 51% rename from spec/unit/content-repo.spec.js rename to spec/unit/content-repo.spec.ts index e773b0577..ce6da80e1 100644 --- a/spec/unit/content-repo.spec.js +++ b/spec/unit/content-repo.spec.ts @@ -19,41 +19,41 @@ describe("ContentRepo", function() { }); it("should return a download URL if no width/height/resize are specified", - function() { - const mxcUri = "mxc://server.name/resourceid"; - expect(getHttpUriForMxc(baseUrl, mxcUri)).toEqual( - baseUrl + "/_matrix/media/r0/download/server.name/resourceid", - ); - }); + function() { + const mxcUri = "mxc://server.name/resourceid"; + expect(getHttpUriForMxc(baseUrl, mxcUri)).toEqual( + baseUrl + "/_matrix/media/r0/download/server.name/resourceid", + ); + }); it("should return the empty string for null input", function() { - expect(getHttpUriForMxc(null)).toEqual(""); + expect(getHttpUriForMxc(null, null)).toEqual(""); }); it("should return a thumbnail URL if a width/height/resize is specified", - function() { - const mxcUri = "mxc://server.name/resourceid"; - expect(getHttpUriForMxc(baseUrl, mxcUri, 32, 64, "crop")).toEqual( - baseUrl + "/_matrix/media/r0/thumbnail/server.name/resourceid" + + function() { + const mxcUri = "mxc://server.name/resourceid"; + expect(getHttpUriForMxc(baseUrl, mxcUri, 32, 64, "crop")).toEqual( + baseUrl + "/_matrix/media/r0/thumbnail/server.name/resourceid" + "?width=32&height=64&method=crop", - ); - }); + ); + }); it("should put fragments from mxc:// URIs after any query parameters", - function() { - const mxcUri = "mxc://server.name/resourceid#automade"; - expect(getHttpUriForMxc(baseUrl, mxcUri, 32)).toEqual( - baseUrl + "/_matrix/media/r0/thumbnail/server.name/resourceid" + + function() { + const mxcUri = "mxc://server.name/resourceid#automade"; + expect(getHttpUriForMxc(baseUrl, mxcUri, 32)).toEqual( + baseUrl + "/_matrix/media/r0/thumbnail/server.name/resourceid" + "?width=32#automade", - ); - }); + ); + }); it("should put fragments from mxc:// URIs at the end of the HTTP URI", - function() { - const mxcUri = "mxc://server.name/resourceid#automade"; - expect(getHttpUriForMxc(baseUrl, mxcUri)).toEqual( - baseUrl + "/_matrix/media/r0/download/server.name/resourceid#automade", - ); - }); + function() { + const mxcUri = "mxc://server.name/resourceid#automade"; + expect(getHttpUriForMxc(baseUrl, mxcUri)).toEqual( + baseUrl + "/_matrix/media/r0/download/server.name/resourceid#automade", + ); + }); }); }); diff --git a/spec/unit/event.spec.js b/spec/unit/event.spec.ts similarity index 57% rename from spec/unit/event.spec.js rename to spec/unit/event.spec.ts index 897d469b6..55ac4c40c 100644 --- a/spec/unit/event.spec.js +++ b/spec/unit/event.spec.ts @@ -1,6 +1,6 @@ /* Copyright 2017 New Vector Ltd -Copyright 2019 The Matrix.org Foundation C.I.C. +Copyright 2019, 2022 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,16 +15,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { logger } from "../../src/logger"; import { MatrixEvent } from "../../src/models/event"; describe("MatrixEvent", () => { describe(".attemptDecryption", () => { let encryptedEvent; + const eventId = 'test_encrypted_event'; beforeEach(() => { encryptedEvent = new MatrixEvent({ - id: 'test_encrypted_event', + event_id: eventId, type: 'm.room.encrypted', content: { ciphertext: 'secrets', @@ -32,45 +32,34 @@ describe("MatrixEvent", () => { }); }); - it('should retry decryption if a retry is queued', () => { - let callCount = 0; - - let prom2; - let prom2Fulfilled = false; + it('should retry decryption if a retry is queued', async () => { + const eventAttemptDecryptionSpy = jest.spyOn(encryptedEvent, 'attemptDecryption'); const crypto = { - decryptEvent: function() { - ++callCount; - logger.log(`decrypt: ${callCount}`); - if (callCount == 1) { + decryptEvent: jest.fn() + .mockImplementationOnce(() => { // schedule a second decryption attempt while // the first one is still running. - prom2 = encryptedEvent.attemptDecryption(crypto); - prom2.then(() => prom2Fulfilled = true); + encryptedEvent.attemptDecryption(crypto); const error = new Error("nope"); error.name = 'DecryptionError'; return Promise.reject(error); - } else { - expect(prom2Fulfilled).toBe( - false, 'second attemptDecryption resolved too soon'); - + }) + .mockImplementationOnce(() => { return Promise.resolve({ clearEvent: { type: 'm.room.message', }, }); - } - }, + }), }; - return encryptedEvent.attemptDecryption(crypto).then(() => { - expect(callCount).toEqual(2); - expect(encryptedEvent.getType()).toEqual('m.room.message'); + await encryptedEvent.attemptDecryption(crypto); - // make sure the second attemptDecryption resolves - return prom2; - }); + expect(eventAttemptDecryptionSpy).toHaveBeenCalledTimes(2); + expect(crypto.decryptEvent).toHaveBeenCalledTimes(2); + expect(encryptedEvent.getType()).toEqual('m.room.message'); }); }); }); diff --git a/spec/unit/filter.spec.js b/spec/unit/filter.spec.ts similarity index 89% rename from spec/unit/filter.spec.js rename to spec/unit/filter.spec.ts index 539df5c46..faa0f53ca 100644 --- a/spec/unit/filter.spec.js +++ b/spec/unit/filter.spec.ts @@ -1,9 +1,9 @@ -import { Filter } from "../../src/filter"; +import { Filter, IFilterDefinition } from "../../src/filter"; describe("Filter", function() { const filterId = "f1lt3ring15g00d4ursoul"; const userId = "@sir_arthur_david:humming.tiger"; - let filter; + let filter: Filter; beforeEach(function() { filter = new Filter(userId); @@ -37,7 +37,7 @@ describe("Filter", function() { describe("setDefinition/getDefinition", function() { it("should set and get the filter body", function() { const definition = { - event_format: "client", + event_format: "client" as IFilterDefinition['event_format'], }; filter.setDefinition(definition); expect(filter.getDefinition()).toEqual(definition); diff --git a/spec/unit/interactive-auth.spec.js b/spec/unit/interactive-auth.spec.ts similarity index 84% rename from spec/unit/interactive-auth.spec.js rename to spec/unit/interactive-auth.spec.ts index 6742d0590..b21a9296a 100644 --- a/spec/unit/interactive-auth.spec.js +++ b/spec/unit/interactive-auth.spec.ts @@ -15,8 +15,9 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { MatrixClient } from "../../src/client"; import { logger } from "../../src/logger"; -import { InteractiveAuth } from "../../src/interactive-auth"; +import { InteractiveAuth, AuthType } from "../../src/interactive-auth"; import { MatrixError } from "../../src/http-api"; import { sleep } from "../../src/utils"; import { randomString } from "../../src/randomstring"; @@ -29,38 +30,40 @@ class FakeClient { } } +const getFakeClient = (): MatrixClient => new FakeClient() as unknown as MatrixClient; + describe("InteractiveAuth", function() { it("should start an auth stage and complete it", function() { const doRequest = jest.fn(); const stateUpdated = jest.fn(); const ia = new InteractiveAuth({ - matrixClient: new FakeClient(), + matrixClient: getFakeClient(), doRequest: doRequest, stateUpdated: stateUpdated, + requestEmailToken: jest.fn(), authData: { session: "sessionId", flows: [ - { stages: ["logintype"] }, + { stages: [AuthType.Password] }, ], params: { - "logintype": { param: "aa" }, + [AuthType.Password]: { param: "aa" }, }, }, }); expect(ia.getSessionId()).toEqual("sessionId"); - expect(ia.getStageParams("logintype")).toEqual({ + expect(ia.getStageParams(AuthType.Password)).toEqual({ param: "aa", }); // first we expect a call here stateUpdated.mockImplementation(function(stage) { logger.log('aaaa'); - expect(stage).toEqual("logintype"); + expect(stage).toEqual(AuthType.Password); ia.submitAuthDict({ - type: "logintype", - foo: "bar", + type: AuthType.Password, }); }); @@ -70,8 +73,7 @@ describe("InteractiveAuth", function() { logger.log('cccc'); expect(authData).toEqual({ session: "sessionId", - type: "logintype", - foo: "bar", + type: AuthType.Password, }); return Promise.resolve(requestRes); }); @@ -86,15 +88,17 @@ describe("InteractiveAuth", function() { it("should make a request if no authdata is provided", function() { const doRequest = jest.fn(); const stateUpdated = jest.fn(); + const requestEmailToken = jest.fn(); const ia = new InteractiveAuth({ - matrixClient: new FakeClient(), - stateUpdated: stateUpdated, - doRequest: doRequest, + matrixClient: getFakeClient(), + stateUpdated, + doRequest, + requestEmailToken, }); expect(ia.getSessionId()).toBe(undefined); - expect(ia.getStageParams("logintype")).toBe(undefined); + expect(ia.getStageParams(AuthType.Password)).toBe(undefined); // first we expect a call to doRequest doRequest.mockImplementation(function(authData) { @@ -103,10 +107,10 @@ describe("InteractiveAuth", function() { const err = new MatrixError({ session: "sessionId", flows: [ - { stages: ["logintype"] }, + { stages: [AuthType.Password] }, ], params: { - "logintype": { param: "aa" }, + [AuthType.Password]: { param: "aa" }, }, }); err.httpStatus = 401; @@ -116,9 +120,9 @@ describe("InteractiveAuth", function() { // .. which should be followed by a call to stateUpdated const requestRes = { "a": "b" }; stateUpdated.mockImplementation(function(stage) { - expect(stage).toEqual("logintype"); + expect(stage).toEqual(AuthType.Password); expect(ia.getSessionId()).toEqual("sessionId"); - expect(ia.getStageParams("logintype")).toEqual({ + expect(ia.getStageParams(AuthType.Password)).toEqual({ param: "aa", }); @@ -127,15 +131,13 @@ describe("InteractiveAuth", function() { logger.log("request2", authData); expect(authData).toEqual({ session: "sessionId", - type: "logintype", - foo: "bar", + type: AuthType.Password, }); return Promise.resolve(requestRes); }); ia.submitAuthDict({ - type: "logintype", - foo: "bar", + type: AuthType.Password, }); }); @@ -149,11 +151,13 @@ describe("InteractiveAuth", function() { it("should start an auth stage and reject if no auth flow", function() { const doRequest = jest.fn(); const stateUpdated = jest.fn(); + const requestEmailToken = jest.fn(); const ia = new InteractiveAuth({ - matrixClient: new FakeClient(), - doRequest: doRequest, - stateUpdated: stateUpdated, + matrixClient: getFakeClient(), + doRequest, + stateUpdated, + requestEmailToken, }); doRequest.mockImplementation(function(authData) { @@ -163,7 +167,7 @@ describe("InteractiveAuth", function() { session: "sessionId", flows: [], params: { - "logintype": { param: "aa" }, + [AuthType.Password]: { param: "aa" }, }, }); err.httpStatus = 401; @@ -183,7 +187,7 @@ describe("InteractiveAuth", function() { requestEmailToken.mockImplementation(async () => ({ sid: "" })); const ia = new InteractiveAuth({ - matrixClient: new FakeClient(), + matrixClient: getFakeClient(), doRequest, stateUpdated, requestEmailToken, }); @@ -210,7 +214,7 @@ describe("InteractiveAuth", function() { requestEmailToken.mockImplementation(async () => ({ sid: "" })); const ia = new InteractiveAuth({ - matrixClient: new FakeClient(), + matrixClient: getFakeClient(), doRequest, stateUpdated, requestEmailToken, }); @@ -239,7 +243,7 @@ describe("InteractiveAuth", function() { }); const ia = new InteractiveAuth({ - matrixClient: new FakeClient(), + matrixClient: getFakeClient(), doRequest, stateUpdated, requestEmailToken, }); @@ -253,7 +257,7 @@ describe("InteractiveAuth", function() { requestEmailToken.mockImplementation(() => sleep(500, { sid: "" })); const ia = new InteractiveAuth({ - matrixClient: new FakeClient(), + matrixClient: getFakeClient(), doRequest, stateUpdated, requestEmailToken, }); @@ -269,7 +273,7 @@ describe("InteractiveAuth", function() { requestEmailToken.mockImplementation(() => sleep(500, { sid })); const ia = new InteractiveAuth({ - matrixClient: new FakeClient(), + matrixClient: getFakeClient(), doRequest, stateUpdated, requestEmailToken, }); diff --git a/spec/unit/login.spec.js b/spec/unit/login.spec.ts similarity index 96% rename from spec/unit/login.spec.js rename to spec/unit/login.spec.ts index 36dc45aa0..f7cf6d307 100644 --- a/spec/unit/login.spec.js +++ b/spec/unit/login.spec.ts @@ -1,7 +1,7 @@ import { TestClient } from '../TestClient'; describe('Login request', function() { - let client; + let client: TestClient; beforeEach(function() { client = new TestClient(); diff --git a/spec/unit/pushprocessor.spec.js b/spec/unit/pushprocessor.spec.ts similarity index 98% rename from spec/unit/pushprocessor.spec.js rename to spec/unit/pushprocessor.spec.ts index 0fab43d07..3bbdd5233 100644 --- a/spec/unit/pushprocessor.spec.js +++ b/spec/unit/pushprocessor.spec.ts @@ -1,15 +1,15 @@ import * as utils from "../test-utils/test-utils"; import { PushProcessor } from "../../src/pushprocessor"; -import { EventType } from "../../src"; +import { EventType, MatrixClient, MatrixEvent } from "../../src"; describe('NotificationService', function() { const testUserId = "@ali:matrix.org"; const testDisplayName = "Alice M"; const testRoomId = "!fl1bb13:localhost"; - let testEvent; + let testEvent: MatrixEvent; - let pushProcessor; + let pushProcessor: PushProcessor; // These would be better if individual rules were configured in the tests themselves. const matrixClient = { @@ -196,7 +196,7 @@ describe('NotificationService', function() { ], }, }, - }; + } as unknown as MatrixClient; beforeEach(function() { testEvent = utils.mkEvent({ diff --git a/spec/unit/realtime-callbacks.spec.js b/spec/unit/realtime-callbacks.spec.ts similarity index 93% rename from spec/unit/realtime-callbacks.spec.js rename to spec/unit/realtime-callbacks.spec.ts index 8e57e48e6..9d3acf1ae 100644 --- a/spec/unit/realtime-callbacks.spec.js +++ b/spec/unit/realtime-callbacks.spec.ts @@ -21,7 +21,7 @@ describe("realtime-callbacks", function() { it("should default to a zero timeout", function() { const callback = jest.fn(); - callbacks.setTimeout(callback); + callbacks.setTimeout(callback, 0); expect(callback).not.toHaveBeenCalled(); tick(0); @@ -38,11 +38,11 @@ describe("realtime-callbacks", function() { it("should set 'this' to the global object", function() { let passed = false; const callback = function() { - expect(this).toBe(global); // eslint-disable-line @babel/no-invalid-this - expect(this.console).toBeTruthy(); // eslint-disable-line @babel/no-invalid-this + expect(this).toBe(global); // eslint-disable-line @typescript-eslint/no-invalid-this + expect(this.console).toBeTruthy(); // eslint-disable-line @typescript-eslint/no-invalid-this passed = true; }; - callbacks.setTimeout(callback); + callbacks.setTimeout(callback, 0); tick(0); expect(passed).toBe(true); }); @@ -92,7 +92,7 @@ describe("realtime-callbacks", function() { expect(callback2).not.toHaveBeenCalled(); }); - callbacks.setTimeout(callback1); + callbacks.setTimeout(callback1, 0); callbacks.setTimeout(callback2, -100); expect(callback1).not.toHaveBeenCalled(); @@ -109,14 +109,14 @@ describe("realtime-callbacks", function() { expect(callback2).not.toHaveBeenCalled(); }); - callbacks.setTimeout(callback1); + callbacks.setTimeout(callback1, 1); expect(callback1).not.toHaveBeenCalled(); expect(callback2).not.toHaveBeenCalled(); - tick(0); + tick(1); expect(callback1).toHaveBeenCalled(); // the fake timer won't actually run callbacks registered during // one tick until the next tick. - tick(1); + tick(2); expect(callback2).toHaveBeenCalled(); }); @@ -139,9 +139,9 @@ describe("realtime-callbacks", function() { describe("cancelTimeout", function() { it("should cancel a pending timeout", function() { const callback = jest.fn(); - const k = callbacks.setTimeout(callback); + const k = callbacks.setTimeout(callback, 10); callbacks.clearTimeout(k); - tick(0); + tick(11); expect(callback).not.toHaveBeenCalled(); }); diff --git a/src/content-repo.ts b/src/content-repo.ts index 333126a00..8ff8a9270 100644 --- a/src/content-repo.ts +++ b/src/content-repo.ts @@ -36,9 +36,9 @@ import * as utils from "./utils"; export function getHttpUriForMxc( baseUrl: string, mxc: string, - width: number, - height: number, - resizeMethod: string, + width?: number, + height?: number, + resizeMethod?: string, allowDirectLinks = false, ): string { if (typeof mxc !== "string" || !mxc) {