Migrate batch of tests to vitest (#34111)
* Migrate batch of tests tro vitest * Iterate * Migrate another test * Fix lockfile
This commit is contained in:
@@ -228,6 +228,7 @@
|
||||
"typescript": "catalog:",
|
||||
"util": "^0.12.5",
|
||||
"vitest": "catalog:",
|
||||
"vitest-canvas-mock": "^1.1.4",
|
||||
"web-streams-polyfill": "^4.0.0",
|
||||
"webpack": "^5.89.0",
|
||||
"webpack-bundle-analyzer": "^5.0.0",
|
||||
|
||||
@@ -6,15 +6,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
import { vi, describe, it, expect, beforeEach, type Mock } from "vitest";
|
||||
import { type Room, type RoomMember, RoomType } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { avatarUrlForRoom } from "../../src/Avatar";
|
||||
import { type Media, mediaFromMxc } from "../../src/customisations/Media";
|
||||
import DMRoomMap from "../../src/utils/DMRoomMap";
|
||||
import { avatarUrlForRoom } from "./Avatar";
|
||||
import { type Media, mediaFromMxc } from "./customisations/Media";
|
||||
import DMRoomMap from "./utils/DMRoomMap";
|
||||
|
||||
jest.mock("../../src/customisations/Media", () => ({
|
||||
mediaFromMxc: jest.fn(),
|
||||
vi.mock("./customisations/Media", () => ({
|
||||
mediaFromMxc: vi.fn(),
|
||||
}));
|
||||
|
||||
const roomId = "!room:example.com";
|
||||
@@ -22,31 +22,31 @@ const avatarUrl1 = "https://example.com/avatar1";
|
||||
const avatarUrl2 = "https://example.com/avatar2";
|
||||
|
||||
describe("avatarUrlForRoom", () => {
|
||||
let getThumbnailOfSourceHttp: jest.Mock;
|
||||
let getThumbnailOfSourceHttp: Mock;
|
||||
let room: Room;
|
||||
let roomMember: RoomMember;
|
||||
let dmRoomMap: DMRoomMap;
|
||||
|
||||
beforeEach(() => {
|
||||
getThumbnailOfSourceHttp = jest.fn();
|
||||
mocked(mediaFromMxc).mockImplementation((): Media => {
|
||||
getThumbnailOfSourceHttp = vi.fn();
|
||||
vi.mocked(mediaFromMxc).mockImplementation((): Media => {
|
||||
return {
|
||||
getThumbnailOfSourceHttp,
|
||||
} as unknown as Media;
|
||||
});
|
||||
room = {
|
||||
roomId,
|
||||
getMxcAvatarUrl: jest.fn(),
|
||||
isSpaceRoom: jest.fn(),
|
||||
getType: jest.fn(),
|
||||
getAvatarFallbackMember: jest.fn(),
|
||||
getMxcAvatarUrl: vi.fn(),
|
||||
isSpaceRoom: vi.fn(),
|
||||
getType: vi.fn(),
|
||||
getAvatarFallbackMember: vi.fn(),
|
||||
} as unknown as Room;
|
||||
dmRoomMap = {
|
||||
getUserIdForRoomId: jest.fn(),
|
||||
getUserIdForRoomId: vi.fn(),
|
||||
} as unknown as DMRoomMap;
|
||||
DMRoomMap.setShared(dmRoomMap);
|
||||
roomMember = {
|
||||
getMxcAvatarUrl: jest.fn(),
|
||||
getMxcAvatarUrl: vi.fn(),
|
||||
} as unknown as RoomMember;
|
||||
});
|
||||
|
||||
@@ -55,40 +55,40 @@ describe("avatarUrlForRoom", () => {
|
||||
});
|
||||
|
||||
it("should return the HTTP source if the room provides a MXC url", () => {
|
||||
mocked(room.getMxcAvatarUrl).mockReturnValue(avatarUrl1);
|
||||
vi.mocked(room.getMxcAvatarUrl).mockReturnValue(avatarUrl1);
|
||||
getThumbnailOfSourceHttp.mockReturnValue(avatarUrl2);
|
||||
expect(avatarUrlForRoom(room, 128, 256, "crop")).toEqual(avatarUrl2);
|
||||
expect(getThumbnailOfSourceHttp).toHaveBeenCalledWith(128, 256, "crop");
|
||||
});
|
||||
|
||||
it("should return null for a space room", () => {
|
||||
mocked(room.isSpaceRoom).mockReturnValue(true);
|
||||
mocked(room.getType).mockReturnValue(RoomType.Space);
|
||||
vi.mocked(room.isSpaceRoom).mockReturnValue(true);
|
||||
vi.mocked(room.getType).mockReturnValue(RoomType.Space);
|
||||
expect(avatarUrlForRoom(room, 128, 128)).toBeNull();
|
||||
});
|
||||
|
||||
it("should return null if the room is not a DM", () => {
|
||||
mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue(undefined);
|
||||
vi.mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue(undefined);
|
||||
expect(avatarUrlForRoom(room, 128, 128)).toBeNull();
|
||||
expect(dmRoomMap.getUserIdForRoomId).toHaveBeenCalledWith(roomId);
|
||||
});
|
||||
|
||||
it("should return null if there is no other member in the room", () => {
|
||||
mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue("@user:example.com");
|
||||
mocked(room.getAvatarFallbackMember).mockReturnValue(undefined);
|
||||
vi.mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue("@user:example.com");
|
||||
vi.mocked(room.getAvatarFallbackMember).mockReturnValue(undefined);
|
||||
expect(avatarUrlForRoom(room, 128, 128)).toBeNull();
|
||||
});
|
||||
|
||||
it("should return null if the other member has no avatar URL", () => {
|
||||
mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue("@user:example.com");
|
||||
mocked(room.getAvatarFallbackMember).mockReturnValue(roomMember);
|
||||
vi.mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue("@user:example.com");
|
||||
vi.mocked(room.getAvatarFallbackMember).mockReturnValue(roomMember);
|
||||
expect(avatarUrlForRoom(room, 128, 128)).toBeNull();
|
||||
});
|
||||
|
||||
it("should return the other member's avatar URL", () => {
|
||||
mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue("@user:example.com");
|
||||
mocked(room.getAvatarFallbackMember).mockReturnValue(roomMember);
|
||||
mocked(roomMember.getMxcAvatarUrl).mockReturnValue(avatarUrl2);
|
||||
vi.mocked(dmRoomMap).getUserIdForRoomId.mockReturnValue("@user:example.com");
|
||||
vi.mocked(room.getAvatarFallbackMember).mockReturnValue(roomMember);
|
||||
vi.mocked(roomMember.getMxcAvatarUrl).mockReturnValue(avatarUrl2);
|
||||
getThumbnailOfSourceHttp.mockReturnValue(avatarUrl2);
|
||||
expect(avatarUrlForRoom(room, 128, 256, "crop")).toEqual(avatarUrl2);
|
||||
expect(getThumbnailOfSourceHttp).toHaveBeenCalledWith(128, 256, "crop");
|
||||
+3
-1
@@ -6,7 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { isKeyComboMatch, type KeyCombo } from "../../src/KeyBindingsManager";
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import { isKeyComboMatch, type KeyCombo } from "./KeyBindingsManager";
|
||||
|
||||
function mockKeyEvent(
|
||||
key: string,
|
||||
@@ -6,37 +6,34 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { Crypto } from "@peculiar/webcrypto";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, beforeEach, afterEach, type MockedObject } from "vitest";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import * as MatrixJs from "matrix-js-sdk/src/matrix";
|
||||
import { decodeBase64, encodeUnpaddedBase64 } from "matrix-js-sdk/src/matrix";
|
||||
import * as encryptAESSecretStorageItemModule from "matrix-js-sdk/src/utils/encryptAESSecretStorageItem";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import fetchMock from "@fetch-mock/vitest";
|
||||
import { flushPromises, getMockClientWithEventEmitter, mockClientMethodsUser, mockPlatformPeg } from "test-utils";
|
||||
import { makeDelegatedAuthConfig } from "test-utils/oidc";
|
||||
|
||||
import StorageEvictedDialog from "../../src/components/views/dialogs/StorageEvictedDialog";
|
||||
import * as Lifecycle from "../../src/Lifecycle";
|
||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||
import Modal from "../../src/Modal";
|
||||
import * as StorageAccess from "../../src/utils/StorageAccess";
|
||||
import { idbSave } from "../../src/utils/StorageAccess";
|
||||
import { flushPromises, getMockClientWithEventEmitter, mockClientMethodsUser, mockPlatformPeg } from "../test-utils";
|
||||
import { OidcClientStore } from "../../src/stores/oidc/OidcClientStore";
|
||||
import { makeDelegatedAuthConfig } from "../test-utils/oidc";
|
||||
import { Action } from "../../src/dispatcher/actions";
|
||||
import PlatformPeg from "../../src/PlatformPeg";
|
||||
import { persistAccessTokenInStorage, persistRefreshTokenInStorage } from "../../src/utils/tokens/tokens";
|
||||
import { encryptPickleKey } from "../../src/utils/tokens/pickling";
|
||||
import * as StorageManager from "../../src/utils/StorageManager.ts";
|
||||
import type BasePlatform from "../../src/BasePlatform.ts";
|
||||
import * as createMatrixClientModule from "../../src/utils/createMatrixClient";
|
||||
import StorageEvictedDialog from "./components/views/dialogs/StorageEvictedDialog";
|
||||
import * as Lifecycle from "./Lifecycle";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import Modal from "./Modal";
|
||||
import * as StorageAccess from "./utils/StorageAccess";
|
||||
import { idbSave } from "./utils/StorageAccess";
|
||||
import { OidcClientStore } from "./stores/oidc/OidcClientStore";
|
||||
import { Action } from "./dispatcher/actions";
|
||||
import PlatformPeg from "./PlatformPeg";
|
||||
import { persistAccessTokenInStorage, persistRefreshTokenInStorage } from "./utils/tokens/tokens";
|
||||
import { encryptPickleKey } from "./utils/tokens/pickling";
|
||||
import * as StorageManager from "./utils/StorageManager.ts";
|
||||
import type BasePlatform from "./BasePlatform.ts";
|
||||
import * as createMatrixClientModule from "./utils/createMatrixClient";
|
||||
|
||||
const { logout, restoreSessionFromStorage, setLoggedIn } = Lifecycle;
|
||||
|
||||
const webCrypto = new Crypto();
|
||||
|
||||
const windowCrypto = window.crypto;
|
||||
|
||||
describe("Lifecycle", () => {
|
||||
const homeserverUrl = "https://domain";
|
||||
const identityServerUrl = "https://is.org";
|
||||
@@ -46,65 +43,55 @@ describe("Lifecycle", () => {
|
||||
|
||||
let mockPlatform: MockedObject<BasePlatform>;
|
||||
|
||||
const realLocalStorage = global.localStorage;
|
||||
|
||||
let mockClient!: MockedObject<MatrixJs.MatrixClient>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
mockPlatform = mockPlatformPeg();
|
||||
mockClient = getMockClientWithEventEmitter({
|
||||
...mockClientMethodsUser(),
|
||||
stopClient: jest.fn(),
|
||||
removeAllListeners: jest.fn(),
|
||||
clearStores: jest.fn(),
|
||||
getAccountData: jest.fn(),
|
||||
getDeviceId: jest.fn().mockReturnValue(deviceId),
|
||||
isVersionSupported: jest.fn().mockResolvedValue(true),
|
||||
getCrypto: jest.fn(),
|
||||
getClientWellKnown: jest.fn(),
|
||||
waitForClientWellKnown: jest.fn(),
|
||||
getThirdpartyProtocols: jest.fn(),
|
||||
stopClient: vi.fn(),
|
||||
removeAllListeners: vi.fn(),
|
||||
clearStores: vi.fn(),
|
||||
getAccountData: vi.fn(),
|
||||
getDeviceId: vi.fn().mockReturnValue(deviceId),
|
||||
isVersionSupported: vi.fn().mockResolvedValue(true),
|
||||
getCrypto: vi.fn(),
|
||||
getClientWellKnown: vi.fn(),
|
||||
waitForClientWellKnown: vi.fn(),
|
||||
getThirdpartyProtocols: vi.fn(),
|
||||
store: {
|
||||
destroy: jest.fn(),
|
||||
destroy: vi.fn(),
|
||||
},
|
||||
getVersions: jest.fn().mockResolvedValue({ versions: ["v1.1"] }),
|
||||
logout: jest.fn().mockResolvedValue(undefined),
|
||||
getAccessToken: jest.fn(),
|
||||
getRefreshToken: jest.fn(),
|
||||
setGuest: jest.fn(),
|
||||
setNotifTimelineSet: jest.fn(),
|
||||
getVersions: vi.fn().mockResolvedValue({ versions: ["v1.1"] }),
|
||||
logout: vi.fn().mockResolvedValue(undefined),
|
||||
getAccessToken: vi.fn(),
|
||||
getRefreshToken: vi.fn(),
|
||||
isInitialSyncComplete: vi.fn(),
|
||||
setGuest: vi.fn(),
|
||||
setNotifTimelineSet: vi.fn(),
|
||||
});
|
||||
// stub this
|
||||
jest.spyOn(MatrixClientPeg, "set").mockImplementation(() => {});
|
||||
jest.spyOn(MatrixClientPeg, "start").mockResolvedValue(undefined);
|
||||
vi.spyOn(MatrixClientPeg, "set").mockImplementation(() => {});
|
||||
vi.spyOn(MatrixClientPeg, "start").mockResolvedValue(undefined);
|
||||
|
||||
// reset any mocking
|
||||
// @ts-ignore mocking
|
||||
delete global.localStorage;
|
||||
global.localStorage = realLocalStorage;
|
||||
vi.spyOn(encryptAESSecretStorageItemModule, "default").mockRestore();
|
||||
|
||||
// @ts-ignore mocking
|
||||
delete window.crypto;
|
||||
window.crypto = webCrypto;
|
||||
|
||||
jest.spyOn(encryptAESSecretStorageItemModule, "default").mockRestore();
|
||||
localStorage.clear();
|
||||
sessionStorage.clear();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
// @ts-ignore unmocking
|
||||
delete window.crypto;
|
||||
window.crypto = windowCrypto;
|
||||
afterEach(() => {
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
const initIdbMock = (mockStore: Record<string, Record<string, unknown>> = {}): void => {
|
||||
jest.spyOn(StorageAccess, "idbLoad")
|
||||
vi.spyOn(StorageAccess, "idbLoad")
|
||||
.mockClear()
|
||||
.mockImplementation(
|
||||
// @ts-ignore mock type
|
||||
async (table: string, key: string) => mockStore[table]?.[key] ?? null,
|
||||
);
|
||||
jest.spyOn(StorageAccess, "idbSave")
|
||||
vi.spyOn(StorageAccess, "idbSave")
|
||||
.mockClear()
|
||||
.mockImplementation(
|
||||
// @ts-ignore mock type
|
||||
@@ -114,13 +101,13 @@ describe("Lifecycle", () => {
|
||||
mockStore[tableKey] = table;
|
||||
},
|
||||
);
|
||||
jest.spyOn(StorageAccess, "idbDelete")
|
||||
vi.spyOn(StorageAccess, "idbDelete")
|
||||
.mockClear()
|
||||
.mockImplementation(async (tableKey: string, key: string | string[]) => {
|
||||
const table = mockStore[tableKey];
|
||||
delete table?.[key as string];
|
||||
});
|
||||
jest.spyOn(StorageAccess, "idbClear")
|
||||
vi.spyOn(StorageAccess, "idbClear")
|
||||
.mockClear()
|
||||
.mockImplementation(async (tableKey: string) => {
|
||||
mockStore[tableKey] = {};
|
||||
@@ -159,14 +146,14 @@ describe("Lifecycle", () => {
|
||||
describe("loadSession", () => {
|
||||
beforeEach(() => {
|
||||
// stub this out
|
||||
jest.spyOn(Modal, "createDialog").mockReturnValue(
|
||||
vi.spyOn(Modal, "createDialog").mockReturnValue(
|
||||
// @ts-ignore allow bad mock
|
||||
{ finished: Promise.resolve([true]) },
|
||||
);
|
||||
});
|
||||
|
||||
it("should not show any error dialog when checkConsistency throws but abortSignal has triggered", async () => {
|
||||
jest.spyOn(StorageManager, "checkConsistency").mockRejectedValue(new Error("test error"));
|
||||
vi.spyOn(StorageManager, "checkConsistency").mockRejectedValue(new Error("test error"));
|
||||
|
||||
const abortController = new AbortController();
|
||||
const prom = Lifecycle.loadSession({
|
||||
@@ -183,27 +170,29 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
describe("restoreSessionFromStorage()", () => {
|
||||
const realLocalStorage = localStorage;
|
||||
|
||||
beforeEach(() => {
|
||||
initIdbMock();
|
||||
|
||||
jest.clearAllMocks();
|
||||
jest.spyOn(logger, "log").mockClear();
|
||||
vi.spyOn(logger, "log").mockClear();
|
||||
|
||||
jest.spyOn(MatrixJs, "createClient").mockReturnValue(mockClient);
|
||||
jest.spyOn(createMatrixClientModule, "createClientWithCreds").mockReturnValue(mockClient);
|
||||
vi.spyOn(MatrixJs, "createClient").mockReturnValue(mockClient);
|
||||
vi.spyOn(createMatrixClientModule, "createClientWithCreds").mockReturnValue(mockClient);
|
||||
|
||||
// stub this out
|
||||
jest.spyOn(Modal, "createDialog").mockReturnValue(
|
||||
vi.spyOn(Modal, "createDialog").mockReturnValue(
|
||||
// @ts-ignore allow bad mock
|
||||
{ finished: Promise.resolve([true]) },
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.stubGlobal("localStorage", realLocalStorage);
|
||||
});
|
||||
|
||||
it("should return false when localStorage is not available", async () => {
|
||||
// @ts-ignore dirty mocking
|
||||
delete global.localStorage;
|
||||
// @ts-ignore dirty mocking
|
||||
global.localStorage = undefined;
|
||||
vi.stubGlobal("localStorage", undefined);
|
||||
|
||||
expect(await restoreSessionFromStorage()).toEqual(false);
|
||||
});
|
||||
@@ -272,7 +261,7 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should persist access token when idb is not available", async () => {
|
||||
jest.spyOn(StorageAccess, "idbSave").mockRejectedValue("oups");
|
||||
vi.spyOn(StorageAccess, "idbSave").mockRejectedValue("oups");
|
||||
expect(await restoreSessionFromStorage()).toEqual(true);
|
||||
|
||||
expect(StorageAccess.idbSave).toHaveBeenCalledWith("account", "mx_access_token", accessToken);
|
||||
@@ -384,7 +373,7 @@ describe("Lifecycle", () => {
|
||||
|
||||
it("should persist access token when idb is not available", async () => {
|
||||
// dont fail for pickle key persist
|
||||
jest.spyOn(StorageAccess, "idbSave").mockImplementation(
|
||||
vi.spyOn(StorageAccess, "idbSave").mockImplementation(
|
||||
async (table: string, key: string | string[]) => {
|
||||
if (table === "account" && key === "mx_access_token") {
|
||||
throw new Error("oups");
|
||||
@@ -406,7 +395,7 @@ describe("Lifecycle", () => {
|
||||
it("should create and start new matrix client with credentials", async () => {
|
||||
// Check that the rust crypto key is as expected. We have to do this during the call, as
|
||||
// the buffer is cleared afterwards.
|
||||
mocked(MatrixClientPeg.start).mockImplementation(async (opts) => {
|
||||
vi.mocked(MatrixClientPeg.start).mockImplementation(async (opts) => {
|
||||
expect(opts?.rustCryptoStoreKey).toEqual(decodeBase64(pickleKey));
|
||||
});
|
||||
|
||||
@@ -559,14 +548,14 @@ describe("Lifecycle", () => {
|
||||
beforeEach(() => {
|
||||
initIdbMock();
|
||||
|
||||
jest.clearAllMocks();
|
||||
jest.spyOn(logger, "log").mockClear();
|
||||
vi.clearAllMocks();
|
||||
vi.spyOn(logger, "log").mockClear();
|
||||
|
||||
jest.spyOn(MatrixJs, "createClient").mockReturnValue(mockClient);
|
||||
vi.spyOn(MatrixJs, "createClient").mockReturnValue(mockClient);
|
||||
// remove any mock implementations
|
||||
jest.spyOn(mockPlatform, "createPickleKey").mockRestore();
|
||||
vi.spyOn(mockPlatform, "createPickleKey").mockRestore();
|
||||
// but still spy and call through
|
||||
jest.spyOn(mockPlatform, "createPickleKey");
|
||||
vi.spyOn(mockPlatform, "createPickleKey");
|
||||
});
|
||||
|
||||
const refreshToken = "test-refresh-token";
|
||||
@@ -617,8 +606,8 @@ describe("Lifecycle", () => {
|
||||
|
||||
describe("without a pickle key", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(mockPlatform, "createPickleKey").mockResolvedValue(null);
|
||||
jest.spyOn(createMatrixClientModule, "createClientWithCreds").mockReturnValue(mockClient);
|
||||
vi.spyOn(mockPlatform, "createPickleKey").mockResolvedValue(null);
|
||||
vi.spyOn(createMatrixClientModule, "createClientWithCreds").mockReturnValue(mockClient);
|
||||
});
|
||||
|
||||
it("should persist credentials", async () => {
|
||||
@@ -650,7 +639,7 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should remove any access token from storage when there is none in credentials and idb save fails", async () => {
|
||||
jest.spyOn(StorageAccess, "idbSave").mockRejectedValue("oups");
|
||||
vi.spyOn(StorageAccess, "idbSave").mockRejectedValue("oups");
|
||||
await setLoggedIn({
|
||||
...credentials,
|
||||
// @ts-ignore
|
||||
@@ -726,7 +715,7 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should persist token when encrypting the token fails", async () => {
|
||||
jest.spyOn(encryptAESSecretStorageItemModule, "default").mockRejectedValue("MOCK REJECT ENCRYPTAES");
|
||||
vi.spyOn(encryptAESSecretStorageItemModule, "default").mockRejectedValue("MOCK REJECT ENCRYPTAES");
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
// persist the unencrypted token
|
||||
@@ -735,13 +724,11 @@ describe("Lifecycle", () => {
|
||||
|
||||
it("should persist token in localStorage when idb fails to save token", async () => {
|
||||
// dont fail for pickle key persist
|
||||
jest.spyOn(StorageAccess, "idbSave").mockImplementation(
|
||||
async (table: string, key: string | string[]) => {
|
||||
if (table === "account" && key === "mx_access_token") {
|
||||
throw new Error("oups");
|
||||
}
|
||||
},
|
||||
);
|
||||
vi.spyOn(StorageAccess, "idbSave").mockImplementation(async (table: string, key: string | string[]) => {
|
||||
if (table === "account" && key === "mx_access_token") {
|
||||
throw new Error("oups");
|
||||
}
|
||||
});
|
||||
await setLoggedIn(credentials);
|
||||
|
||||
// put plain accessToken in localstorage when we dont have idb
|
||||
@@ -750,13 +737,11 @@ describe("Lifecycle", () => {
|
||||
|
||||
it("should remove any access token from storage when there is none in credentials and idb save fails", async () => {
|
||||
// dont fail for pickle key persist
|
||||
jest.spyOn(StorageAccess, "idbSave").mockImplementation(
|
||||
async (table: string, key: string | string[]) => {
|
||||
if (table === "account" && key === "mx_access_token") {
|
||||
throw new Error("oups");
|
||||
}
|
||||
},
|
||||
);
|
||||
vi.spyOn(StorageAccess, "idbSave").mockImplementation(async (table: string, key: string | string[]) => {
|
||||
if (table === "account" && key === "mx_access_token") {
|
||||
throw new Error("oups");
|
||||
}
|
||||
});
|
||||
await setLoggedIn({
|
||||
...credentials,
|
||||
// @ts-ignore
|
||||
@@ -768,7 +753,7 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should create new matrix client with credentials", async () => {
|
||||
jest.spyOn(createMatrixClientModule, "createClientWithCreds").mockReturnValue(mockClient);
|
||||
vi.spyOn(createMatrixClientModule, "createClientWithCreds").mockReturnValue(mockClient);
|
||||
expect(await setLoggedIn(credentials)).toEqual(mockClient);
|
||||
|
||||
expect(createMatrixClientModule.createClientWithCreds).toHaveBeenCalledWith(
|
||||
@@ -903,7 +888,7 @@ describe("Lifecycle", () => {
|
||||
beforeEach(() => {
|
||||
oidcClientStore = new OidcClientStore(mockClient);
|
||||
// stub
|
||||
jest.spyOn(oidcClientStore, "revokeTokens").mockResolvedValue(undefined);
|
||||
vi.spyOn(oidcClientStore, "revokeTokens").mockResolvedValue(undefined);
|
||||
|
||||
mockClient.getAccessToken.mockReturnValue(accessToken);
|
||||
mockClient.getRefreshToken.mockReturnValue(refreshToken);
|
||||
@@ -918,7 +903,7 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should call logout on the client when oidcClientStore.isUserAuthenticatedWithOidc is falsy", async () => {
|
||||
jest.spyOn(oidcClientStore, "isUserAuthenticatedWithOidc", "get").mockReturnValue(false);
|
||||
vi.spyOn(oidcClientStore, "isUserAuthenticatedWithOidc", "get").mockReturnValue(false);
|
||||
logout(oidcClientStore);
|
||||
|
||||
await flushPromises();
|
||||
@@ -928,7 +913,7 @@ describe("Lifecycle", () => {
|
||||
});
|
||||
|
||||
it("should revoke tokens when user is authenticated with oidc", async () => {
|
||||
jest.spyOn(oidcClientStore, "isUserAuthenticatedWithOidc", "get").mockReturnValue(true);
|
||||
vi.spyOn(oidcClientStore, "isUserAuthenticatedWithOidc", "get").mockReturnValue(true);
|
||||
logout(oidcClientStore);
|
||||
|
||||
await flushPromises();
|
||||
@@ -940,12 +925,12 @@ describe("Lifecycle", () => {
|
||||
|
||||
describe("overwritelogin", () => {
|
||||
beforeEach(async () => {
|
||||
jest.spyOn(MatrixJs, "createClient").mockReturnValue(mockClient);
|
||||
vi.spyOn(MatrixJs, "createClient").mockReturnValue(mockClient);
|
||||
});
|
||||
|
||||
it("should replace the current login with a new one", async () => {
|
||||
const stopSpy = jest.spyOn(mockClient, "stopClient").mockReturnValue(undefined);
|
||||
jest.spyOn(createMatrixClientModule, "createClientWithCreds").mockReturnValue(mockClient);
|
||||
const stopSpy = vi.spyOn(mockClient, "stopClient").mockReturnValue(undefined);
|
||||
vi.spyOn(createMatrixClientModule, "createClientWithCreds").mockReturnValue(mockClient);
|
||||
const dis = window.mxDispatcher;
|
||||
|
||||
const firstLoginEvent: Promise<void> = new Promise((resolve) => {
|
||||
@@ -963,7 +948,7 @@ describe("Lifecycle", () => {
|
||||
expect(stopSpy).toHaveBeenCalledTimes(1);
|
||||
// important the overwrite action should not call unset before replacing.
|
||||
// So spy on it and make sure it's not called.
|
||||
jest.spyOn(MatrixClientPeg, "unset").mockReturnValue(undefined);
|
||||
vi.spyOn(MatrixClientPeg, "unset").mockReturnValue(undefined);
|
||||
|
||||
expect(createMatrixClientModule.createClientWithCreds).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
@@ -6,7 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import Markdown from "../../src/Markdown";
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import Markdown from "./Markdown";
|
||||
|
||||
describe("Markdown parser test", () => {
|
||||
describe("fixing HTML links", () => {
|
||||
+51
-54
@@ -7,41 +7,38 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
|
||||
import { type PostHog } from "posthog-js";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { type CryptoApi } from "matrix-js-sdk/src/crypto-api";
|
||||
import { getMockClientWithEventEmitter } from "test-utils";
|
||||
|
||||
import {
|
||||
Anonymity,
|
||||
getRedactedCurrentLocation,
|
||||
type IPosthogEvent,
|
||||
PosthogAnalytics,
|
||||
} from "../../src/PosthogAnalytics";
|
||||
import SdkConfig from "../../src/SdkConfig";
|
||||
import { getMockClientWithEventEmitter } from "../test-utils";
|
||||
import SettingsStore from "../../src/settings/SettingsStore";
|
||||
import { Layout } from "../../src/settings/enums/Layout";
|
||||
import defaultDispatcher from "../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../src/dispatcher/actions";
|
||||
import { SettingLevel } from "../../src/settings/SettingLevel";
|
||||
import { Anonymity, getRedactedCurrentLocation, type IPosthogEvent, PosthogAnalytics } from "./PosthogAnalytics";
|
||||
import SdkConfig from "./SdkConfig";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import { Layout } from "./settings/enums/Layout";
|
||||
import defaultDispatcher from "./dispatcher/dispatcher";
|
||||
import { Action } from "./dispatcher/actions";
|
||||
import { SettingLevel } from "./settings/SettingLevel";
|
||||
|
||||
const getFakePosthog = (): PostHog =>
|
||||
({
|
||||
capture: jest.fn(),
|
||||
init: jest.fn(),
|
||||
identify: jest.fn(),
|
||||
reset: jest.fn(),
|
||||
register: jest.fn(),
|
||||
get_distinct_id: jest.fn(),
|
||||
capture: vi.fn(),
|
||||
init: vi.fn(),
|
||||
identify: vi.fn(),
|
||||
reset: vi.fn(),
|
||||
register: vi.fn(),
|
||||
get_distinct_id: vi.fn(),
|
||||
persistence: {
|
||||
get_property: jest.fn(),
|
||||
get_property: vi.fn(),
|
||||
},
|
||||
identifyUser: jest.fn(),
|
||||
identifyUser: vi.fn(),
|
||||
}) as unknown as PostHog;
|
||||
|
||||
interface ITestEvent extends IPosthogEvent {
|
||||
eventName: "JestTestEvents";
|
||||
eventName: "TestEvents";
|
||||
foo?: string;
|
||||
}
|
||||
|
||||
@@ -121,17 +118,17 @@ describe("PosthogAnalytics", () => {
|
||||
it("Should pass event to posthog", () => {
|
||||
analytics.setAnonymity(Anonymity.Pseudonymous);
|
||||
analytics.trackEvent<ITestEvent>({
|
||||
eventName: "JestTestEvents",
|
||||
eventName: "TestEvents",
|
||||
foo: "bar",
|
||||
});
|
||||
expect(mocked(fakePosthog).capture.mock.calls[0][0]).toBe("JestTestEvents");
|
||||
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["foo"]).toEqual("bar");
|
||||
expect(vi.mocked(fakePosthog).capture.mock.calls[0][0]).toBe("TestEvents");
|
||||
expect(vi.mocked(fakePosthog).capture.mock.calls[0][1]!["foo"]).toEqual("bar");
|
||||
});
|
||||
|
||||
it("Should not track events if anonymous", async () => {
|
||||
analytics.setAnonymity(Anonymity.Anonymous);
|
||||
await analytics.trackEvent<ITestEvent>({
|
||||
eventName: "JestTestEvents",
|
||||
eventName: "TestEvents",
|
||||
foo: "bar",
|
||||
});
|
||||
expect(fakePosthog.capture).not.toHaveBeenCalled();
|
||||
@@ -140,7 +137,7 @@ describe("PosthogAnalytics", () => {
|
||||
it("Should not track any events if disabled", async () => {
|
||||
analytics.setAnonymity(Anonymity.Disabled);
|
||||
analytics.trackEvent<ITestEvent>({
|
||||
eventName: "JestTestEvents",
|
||||
eventName: "TestEvents",
|
||||
foo: "bar",
|
||||
});
|
||||
expect(fakePosthog.capture).not.toHaveBeenCalled();
|
||||
@@ -164,29 +161,29 @@ describe("PosthogAnalytics", () => {
|
||||
it("Should identify the user to posthog if pseudonymous", async () => {
|
||||
analytics.setAnonymity(Anonymity.Pseudonymous);
|
||||
const client = getMockClientWithEventEmitter({
|
||||
getAccountDataFromServer: jest.fn().mockResolvedValue(null),
|
||||
setAccountData: jest.fn().mockResolvedValue({}),
|
||||
getAccountDataFromServer: vi.fn().mockResolvedValue(null),
|
||||
setAccountData: vi.fn().mockResolvedValue({}),
|
||||
});
|
||||
await analytics.identifyUser(client, () => "analytics_id");
|
||||
expect(mocked(fakePosthog).identify.mock.calls[0][0]).toBe("analytics_id");
|
||||
expect(vi.mocked(fakePosthog).identify.mock.calls[0][0]).toBe("analytics_id");
|
||||
});
|
||||
|
||||
it("Should not identify the user to posthog if anonymous", async () => {
|
||||
analytics.setAnonymity(Anonymity.Anonymous);
|
||||
const client = getMockClientWithEventEmitter({});
|
||||
await analytics.identifyUser(client, () => "analytics_id");
|
||||
expect(mocked(fakePosthog).identify.mock.calls.length).toBe(0);
|
||||
expect(vi.mocked(fakePosthog).identify.mock.calls.length).toBe(0);
|
||||
});
|
||||
|
||||
it("Should identify using the server's analytics id if present", async () => {
|
||||
analytics.setAnonymity(Anonymity.Pseudonymous);
|
||||
|
||||
const client = getMockClientWithEventEmitter({
|
||||
getAccountDataFromServer: jest.fn().mockResolvedValue({ id: "existing_analytics_id" }),
|
||||
setAccountData: jest.fn().mockResolvedValue({}),
|
||||
getAccountDataFromServer: vi.fn().mockResolvedValue({ id: "existing_analytics_id" }),
|
||||
setAccountData: vi.fn().mockResolvedValue({}),
|
||||
});
|
||||
await analytics.identifyUser(client, () => "new_analytics_id");
|
||||
expect(mocked(fakePosthog).identify.mock.calls[0][0]).toBe("existing_analytics_id");
|
||||
expect(vi.mocked(fakePosthog).identify.mock.calls[0][0]).toBe("existing_analytics_id");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -220,9 +217,9 @@ describe("PosthogAnalytics", () => {
|
||||
true,
|
||||
);
|
||||
analytics.trackEvent<ITestEvent>({
|
||||
eventName: "JestTestEvents",
|
||||
eventName: "TestEvents",
|
||||
});
|
||||
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
expect(vi.mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
WebLayout: "IRC",
|
||||
});
|
||||
});
|
||||
@@ -237,9 +234,9 @@ describe("PosthogAnalytics", () => {
|
||||
true,
|
||||
);
|
||||
analytics.trackEvent<ITestEvent>({
|
||||
eventName: "JestTestEvents",
|
||||
eventName: "TestEvents",
|
||||
});
|
||||
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
expect(vi.mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
WebLayout: "Bubble",
|
||||
});
|
||||
});
|
||||
@@ -254,9 +251,9 @@ describe("PosthogAnalytics", () => {
|
||||
true,
|
||||
);
|
||||
analytics.trackEvent<ITestEvent>({
|
||||
eventName: "JestTestEvents",
|
||||
eventName: "TestEvents",
|
||||
});
|
||||
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
expect(vi.mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
WebLayout: "Group",
|
||||
});
|
||||
});
|
||||
@@ -272,10 +269,10 @@ describe("PosthogAnalytics", () => {
|
||||
true,
|
||||
);
|
||||
analytics.trackEvent<ITestEvent>({
|
||||
eventName: "JestTestEvents",
|
||||
eventName: "TestEvents",
|
||||
});
|
||||
console.log(mocked(fakePosthog).capture.mock.calls[0]);
|
||||
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
console.log(vi.mocked(fakePosthog).capture.mock.calls[0]);
|
||||
expect(vi.mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
WebLayout: "Compact",
|
||||
});
|
||||
});
|
||||
@@ -311,9 +308,9 @@ describe("PosthogAnalytics", () => {
|
||||
true,
|
||||
);
|
||||
analytics.trackEvent<ITestEvent>({
|
||||
eventName: "JestTestEvents",
|
||||
eventName: "TestEvents",
|
||||
});
|
||||
expect(mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
expect(vi.mocked(fakePosthog).capture.mock.calls[0][1]!["$set"]).toMatchObject({
|
||||
URLPreviewsEnabled: true,
|
||||
});
|
||||
});
|
||||
@@ -323,10 +320,10 @@ describe("PosthogAnalytics", () => {
|
||||
let analytics: PosthogAnalytics;
|
||||
const getFakeClient = (): MatrixClient =>
|
||||
({
|
||||
getCrypto: jest.fn(),
|
||||
setAccountData: jest.fn(),
|
||||
getCrypto: vi.fn(),
|
||||
setAccountData: vi.fn(),
|
||||
// just fake return an `im.vector.analytics` content
|
||||
getAccountDataFromServer: jest.fn().mockReturnValue({
|
||||
getAccountDataFromServer: vi.fn().mockReturnValue({
|
||||
id: "0000000",
|
||||
pseudonymousAnalyticsOptIn: true,
|
||||
}),
|
||||
@@ -350,7 +347,7 @@ describe("PosthogAnalytics", () => {
|
||||
// To simulate a switch we call updateAnonymityFromSettings.
|
||||
// As per documentation this function is called On login.
|
||||
const mockClient = getFakeClient();
|
||||
mocked(mockClient.getCrypto).mockReturnValue({
|
||||
vi.mocked(mockClient.getCrypto).mockReturnValue({
|
||||
getVersion: () => {
|
||||
return rustBackend ? "Rust SDK 0.6.0 (9c6b550), Vodozemac 0.5.0" : "Olm 3.2.0";
|
||||
},
|
||||
@@ -363,7 +360,7 @@ describe("PosthogAnalytics", () => {
|
||||
|
||||
await simulateLogin(false);
|
||||
|
||||
expect(mocked(fakePosthog).register.mock.lastCall![0]["cryptoSDK"]).toStrictEqual("Legacy");
|
||||
expect(vi.mocked(fakePosthog).register.mock.lastCall![0]["cryptoSDK"]).toStrictEqual("Legacy");
|
||||
});
|
||||
|
||||
it("should send Legacy cryptoSDK superProperty correctly", async () => {
|
||||
@@ -373,7 +370,7 @@ describe("PosthogAnalytics", () => {
|
||||
|
||||
// Super Properties are properties associated with events that are set once and then sent with every capture call.
|
||||
// They are set using posthog.register
|
||||
expect(mocked(fakePosthog).register.mock.lastCall![0]["cryptoSDK"]).toStrictEqual("Legacy");
|
||||
expect(vi.mocked(fakePosthog).register.mock.lastCall![0]["cryptoSDK"]).toStrictEqual("Legacy");
|
||||
});
|
||||
|
||||
it("should send cryptoSDK superProperty when enabling analytics", async () => {
|
||||
@@ -383,13 +380,13 @@ describe("PosthogAnalytics", () => {
|
||||
|
||||
// This initial call is due to the call to register platformSuperProperties
|
||||
// The important thing is that the cryptoSDK superProperty is not set.
|
||||
expect(mocked(fakePosthog).register.mock.lastCall![0]).toStrictEqual({});
|
||||
expect(vi.mocked(fakePosthog).register.mock.lastCall![0]).toStrictEqual({});
|
||||
|
||||
// switching to pseudonymous should ensure that the cryptoSDK superProperty is set correctly
|
||||
analytics.setAnonymity(Anonymity.Pseudonymous);
|
||||
// Super Properties are properties associated with events that are set once and then sent with every capture call.
|
||||
// They are set using posthog.register
|
||||
expect(mocked(fakePosthog).register.mock.lastCall![0]["cryptoSDK"]).toStrictEqual("Rust");
|
||||
expect(vi.mocked(fakePosthog).register.mock.lastCall![0]["cryptoSDK"]).toStrictEqual("Rust");
|
||||
});
|
||||
});
|
||||
});
|
||||
+8
-4
@@ -5,16 +5,20 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { PosthogAnalytics } from "../../src/PosthogAnalytics";
|
||||
import PosthogTrackers from "../../src/PosthogTrackers";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, afterEach } from "vitest";
|
||||
|
||||
import { PosthogAnalytics } from "./PosthogAnalytics";
|
||||
import PosthogTrackers from "./PosthogTrackers";
|
||||
|
||||
describe("PosthogTrackers", () => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
it("tracks URL Previews", () => {
|
||||
jest.spyOn(PosthogAnalytics.instance, "trackEvent");
|
||||
vi.spyOn(PosthogAnalytics.instance, "trackEvent");
|
||||
const tracker = new PosthogTrackers();
|
||||
tracker.trackUrlPreview("$123456", false, [
|
||||
{
|
||||
@@ -6,7 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, beforeEach, type Mocked } from "vitest";
|
||||
import {
|
||||
PushRuleActionName,
|
||||
TweakName,
|
||||
@@ -19,19 +21,19 @@ import {
|
||||
type MatrixClient,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { mkEvent, mkRoom, mkRoomMember, muteRoom, stubClient, upsertRoomStateEvents } from "test-utils";
|
||||
import { mkThread } from "test-utils/threads";
|
||||
|
||||
import { mkEvent, mkRoom, mkRoomMember, muteRoom, stubClient, upsertRoomStateEvents } from "../test-utils";
|
||||
import {
|
||||
getRoomNotifsState,
|
||||
RoomNotifState,
|
||||
getUnreadNotificationCount,
|
||||
determineUnreadState,
|
||||
getUnsentMessages,
|
||||
} from "../../src/RoomNotifs";
|
||||
import { NotificationLevel } from "../../src/stores/notifications/NotificationLevel";
|
||||
import SettingsStore from "../../src/settings/SettingsStore";
|
||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||
import { mkThread } from "../test-utils/threads";
|
||||
} from "./RoomNotifs";
|
||||
import { NotificationLevel } from "./stores/notifications/NotificationLevel";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
|
||||
describe("getUnsentMessages", () => {
|
||||
const ROOM_ID = "!roomId";
|
||||
@@ -95,14 +97,14 @@ describe("getUnsentMessages", () => {
|
||||
});
|
||||
|
||||
describe("RoomNotifs test", () => {
|
||||
let client: jest.Mocked<MatrixClient>;
|
||||
let client: Mocked<MatrixClient>;
|
||||
|
||||
beforeEach(() => {
|
||||
client = stubClient() as jest.Mocked<MatrixClient>;
|
||||
client = stubClient() as Mocked<MatrixClient>;
|
||||
});
|
||||
|
||||
it("getRoomNotifsState handles rules with no conditions", () => {
|
||||
mocked(client).pushRules = {
|
||||
vi.mocked(client).pushRules = {
|
||||
global: {
|
||||
override: [
|
||||
{
|
||||
@@ -118,7 +120,7 @@ describe("RoomNotifs test", () => {
|
||||
});
|
||||
|
||||
it("getRoomNotifsState handles guest users", () => {
|
||||
mocked(client).isGuest.mockReturnValue(true);
|
||||
vi.mocked(client).isGuest.mockReturnValue(true);
|
||||
expect(getRoomNotifsState(client, "!roomId:server")).toBe(RoomNotifState.AllMessages);
|
||||
});
|
||||
|
||||
@@ -258,7 +260,7 @@ describe("RoomNotifs test", () => {
|
||||
|
||||
describe("and dynamic room predecessors are enabled", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
vi.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
(settingName) => settingName === "feature_dynamic_room_predecessors",
|
||||
);
|
||||
});
|
||||
@@ -343,7 +345,7 @@ describe("RoomNotifs test", () => {
|
||||
});
|
||||
|
||||
it("indicates the user knock has been denied", async () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((name) => {
|
||||
vi.spyOn(SettingsStore, "getValue").mockImplementation((name) => {
|
||||
return name === "feature_ask_to_join";
|
||||
});
|
||||
const roomMember = mkRoomMember(
|
||||
@@ -355,7 +357,7 @@ describe("RoomNotifs test", () => {
|
||||
membership: KnownMembership.Knock,
|
||||
},
|
||||
);
|
||||
jest.spyOn(room, "getMember").mockReturnValue(roomMember);
|
||||
vi.spyOn(room, "getMember").mockReturnValue(roomMember);
|
||||
const { level, symbol, count } = determineUnreadState(room);
|
||||
|
||||
expect(symbol).toBe("!");
|
||||
@@ -6,11 +6,13 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
import { EventType, type MatrixClient, type MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { setDMRoom } from "../../src/Rooms";
|
||||
import { mkEvent, stubClient } from "../test-utils";
|
||||
import { vi, describe, it, expect, beforeEach } from "vitest";
|
||||
import { EventType, type MatrixClient, type MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { mkEvent, stubClient } from "test-utils";
|
||||
|
||||
import { setDMRoom } from "./Rooms";
|
||||
|
||||
describe("setDMRoom", () => {
|
||||
const userId1 = "@user1:example.com";
|
||||
@@ -23,8 +25,8 @@ describe("setDMRoom", () => {
|
||||
let client: MatrixClient;
|
||||
|
||||
beforeEach(() => {
|
||||
client = mocked(stubClient());
|
||||
client.getAccountData = jest.fn().mockImplementation((eventType: string): MatrixEvent | undefined => {
|
||||
client = vi.mocked(stubClient());
|
||||
client.getAccountData = vi.fn().mockImplementation((eventType: string): MatrixEvent | undefined => {
|
||||
if (eventType === EventType.Direct) {
|
||||
return mkEvent({
|
||||
event: true,
|
||||
@@ -43,7 +45,7 @@ describe("setDMRoom", () => {
|
||||
|
||||
describe("when logged in as a guest and marking a room as DM", () => {
|
||||
beforeEach(() => {
|
||||
mocked(client.isGuest).mockReturnValue(true);
|
||||
vi.mocked(client.isGuest).mockReturnValue(true);
|
||||
setDMRoom(client, roomId1, userId1);
|
||||
});
|
||||
|
||||
@@ -94,7 +96,7 @@ describe("setDMRoom", () => {
|
||||
|
||||
describe("when the direct event is undefined", () => {
|
||||
beforeEach(() => {
|
||||
mocked(client.getAccountData).mockReturnValue(undefined);
|
||||
vi.mocked(client.getAccountData).mockReturnValue(undefined);
|
||||
setDMRoom(client, roomId1, userId1);
|
||||
});
|
||||
|
||||
@@ -108,8 +110,8 @@ describe("setDMRoom", () => {
|
||||
describe("when the current content is undefined", () => {
|
||||
beforeEach(() => {
|
||||
// @ts-ignore
|
||||
mocked(client.getAccountData).mockReturnValue({
|
||||
getContent: jest.fn(),
|
||||
vi.mocked(client.getAccountData).mockReturnValue({
|
||||
getContent: vi.fn(),
|
||||
});
|
||||
setDMRoom(client, roomId1, userId1);
|
||||
});
|
||||
+17
-15
@@ -6,14 +6,16 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import ScalarAuthClient from "../../src/ScalarAuthClient";
|
||||
import { stubClient } from "../test-utils";
|
||||
import SdkConfig from "../../src/SdkConfig";
|
||||
import { WidgetType } from "../../src/widgets/WidgetType";
|
||||
import { vi, describe, it, expect, beforeEach } from "vitest";
|
||||
import fetchMock from "@fetch-mock/vitest";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { stubClient } from "test-utils";
|
||||
|
||||
import ScalarAuthClient from "./ScalarAuthClient";
|
||||
import SdkConfig from "./SdkConfig";
|
||||
import { WidgetType } from "./widgets/WidgetType";
|
||||
|
||||
describe("ScalarAuthClient", function () {
|
||||
const apiUrl = "https://test.com/api";
|
||||
@@ -27,7 +29,7 @@ describe("ScalarAuthClient", function () {
|
||||
|
||||
let client: MatrixClient;
|
||||
beforeEach(function () {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
client = stubClient();
|
||||
});
|
||||
|
||||
@@ -42,9 +44,9 @@ describe("ScalarAuthClient", function () {
|
||||
body: { user_id: client.getUserId() },
|
||||
});
|
||||
|
||||
client.getOpenIdToken = jest.fn().mockResolvedValue(tokenObject);
|
||||
client.getOpenIdToken = vi.fn().mockResolvedValue(tokenObject);
|
||||
|
||||
sac.exchangeForScalarToken = jest.fn((arg) => {
|
||||
sac.exchangeForScalarToken = vi.fn((arg) => {
|
||||
return Promise.resolve(arg === tokenObject ? "wokentoken" : "othertoken");
|
||||
});
|
||||
|
||||
@@ -91,13 +93,13 @@ describe("ScalarAuthClient", function () {
|
||||
describe("registerForToken", () => {
|
||||
it("should call `termsInteractionCallback` upon M_TERMS_NOT_SIGNED error", async () => {
|
||||
const sac = new ScalarAuthClient(apiUrl + 4, uiUrl);
|
||||
const termsInteractionCallback = jest.fn();
|
||||
const termsInteractionCallback = vi.fn();
|
||||
sac.setTermsInteractionCallback(termsInteractionCallback);
|
||||
fetchMock.get("https://test.com/api4/account?scalar_token=testtoken1&v=1.1", {
|
||||
body: { errcode: "M_TERMS_NOT_SIGNED" },
|
||||
});
|
||||
sac.exchangeForScalarToken = jest.fn(() => Promise.resolve("testtoken1"));
|
||||
mocked(client.getTerms).mockResolvedValue({ policies: {} });
|
||||
sac.exchangeForScalarToken = vi.fn(() => Promise.resolve("testtoken1"));
|
||||
vi.mocked(client.getTerms).mockResolvedValue({ policies: {} });
|
||||
|
||||
await expect(sac.registerForToken()).resolves.toBe("testtoken1");
|
||||
});
|
||||
@@ -108,7 +110,7 @@ describe("ScalarAuthClient", function () {
|
||||
body: { errcode: "SERVER_IS_SAD" },
|
||||
status: 500,
|
||||
});
|
||||
sac.exchangeForScalarToken = jest.fn(() => Promise.resolve("testtoken2"));
|
||||
sac.exchangeForScalarToken = vi.fn(() => Promise.resolve("testtoken2"));
|
||||
|
||||
await expect(sac.registerForToken()).rejects.toBeTruthy();
|
||||
});
|
||||
@@ -118,7 +120,7 @@ describe("ScalarAuthClient", function () {
|
||||
fetchMock.get("https://test.com/api6/account?scalar_token=testtoken3&v=1.1", {
|
||||
body: {},
|
||||
});
|
||||
sac.exchangeForScalarToken = jest.fn(() => Promise.resolve("testtoken3"));
|
||||
sac.exchangeForScalarToken = vi.fn(() => Promise.resolve("testtoken3"));
|
||||
|
||||
await expect(sac.registerForToken()).rejects.toThrow("Missing user_id in response");
|
||||
});
|
||||
@@ -6,7 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import SdkConfig, { DEFAULTS } from "../../src/SdkConfig";
|
||||
import { describe, it, expect, beforeEach } from "vitest";
|
||||
|
||||
import SdkConfig, { DEFAULTS } from "./SdkConfig";
|
||||
|
||||
describe("SdkConfig", () => {
|
||||
describe("with default values", () => {
|
||||
+12
-9
@@ -6,17 +6,20 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, beforeEach } from "vitest";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
import { getBrowserSupport, checkBrowserSupport, LOCAL_STORAGE_KEY } from "../../src/SupportedBrowser";
|
||||
import ToastStore from "../../src/stores/ToastStore";
|
||||
import GenericToast from "../../src/components/views/toasts/GenericToast";
|
||||
import { getBrowserSupport, checkBrowserSupport, LOCAL_STORAGE_KEY } from "./SupportedBrowser";
|
||||
import ToastStore from "./stores/ToastStore";
|
||||
import GenericToast from "./components/views/toasts/GenericToast";
|
||||
|
||||
jest.mock("matrix-js-sdk/src/logger");
|
||||
vi.mock("matrix-js-sdk/src/logger");
|
||||
|
||||
describe("SupportedBrowser", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
vi.resetAllMocks();
|
||||
localStorage.clear();
|
||||
getBrowserSupport.clear();
|
||||
});
|
||||
@@ -24,8 +27,8 @@ describe("SupportedBrowser", () => {
|
||||
const testUserAgentFactory =
|
||||
(expectedWarning?: string) =>
|
||||
async (userAgent: string): Promise<void> => {
|
||||
const toastSpy = jest.spyOn(ToastStore.sharedInstance(), "addOrReplaceToast");
|
||||
const warnLogSpy = jest.spyOn(logger, "warn");
|
||||
const toastSpy = vi.spyOn(ToastStore.sharedInstance(), "addOrReplaceToast");
|
||||
const warnLogSpy = vi.spyOn(logger, "warn");
|
||||
Object.defineProperty(window, "navigator", { value: { userAgent: userAgent }, writable: true });
|
||||
checkBrowserSupport();
|
||||
if (expectedWarning) {
|
||||
@@ -91,8 +94,8 @@ describe("SupportedBrowser", () => {
|
||||
);
|
||||
|
||||
it("should not warn for unsupported browser if user accepted already", async () => {
|
||||
const toastSpy = jest.spyOn(ToastStore.sharedInstance(), "addOrReplaceToast");
|
||||
const warnLogSpy = jest.spyOn(logger, "warn");
|
||||
const toastSpy = vi.spyOn(ToastStore.sharedInstance(), "addOrReplaceToast");
|
||||
const warnLogSpy = vi.spyOn(logger, "warn");
|
||||
const userAgent =
|
||||
"Mozilla/5.0 (X11; CrOS x86_64 15633.69.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.6045.212 Safari/537.36";
|
||||
Object.defineProperty(window, "navigator", { value: { userAgent: userAgent }, writable: true });
|
||||
+5
-1
@@ -8,7 +8,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import * as tzh from "../../src/TimezoneHandler";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import * as tzh from "./TimezoneHandler";
|
||||
|
||||
describe("TimezoneHandler", () => {
|
||||
it("should support setting a user timezone", async () => {
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Favicon should clear a badge if called with a zero value 1`] = `
|
||||
exports[`Favicon > should clear a badge if called with a zero value 1`] = `
|
||||
[
|
||||
{
|
||||
"props": {
|
||||
@@ -236,7 +236,7 @@ exports[`Favicon should clear a badge if called with a zero value 1`] = `
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Favicon should draw a badge if called with a non-zero value 1`] = `
|
||||
exports[`Favicon > should draw a badge if called with a non-zero value 1`] = `
|
||||
[
|
||||
{
|
||||
"props": {
|
||||
@@ -6,15 +6,18 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import "jest-canvas-mock";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import Favicon from "../../src/favicon";
|
||||
import { vi, describe, it, expect, beforeEach } from "vitest";
|
||||
import "vitest-canvas-mock";
|
||||
|
||||
jest.useFakeTimers();
|
||||
import Favicon from "./favicon";
|
||||
|
||||
vi.useFakeTimers();
|
||||
|
||||
describe("Favicon", () => {
|
||||
beforeEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
document.getElementsByTagName("head")[0]?.remove();
|
||||
const head = document.createElement("head");
|
||||
window.document.documentElement.prepend(head);
|
||||
@@ -30,14 +33,14 @@ describe("Favicon", () => {
|
||||
it("should draw a badge if called with a non-zero value", () => {
|
||||
const favicon = new Favicon();
|
||||
favicon.badge(123);
|
||||
jest.runAllTimers();
|
||||
vi.runAllTimers();
|
||||
expect(favicon["context"].__getDrawCalls()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should clear a badge if called with a zero value", () => {
|
||||
const favicon = new Favicon();
|
||||
favicon.badge(123);
|
||||
jest.runAllTimers();
|
||||
vi.runAllTimers();
|
||||
favicon.badge(0);
|
||||
expect(favicon["context"].__getDrawCalls()).toMatchSnapshot();
|
||||
});
|
||||
@@ -48,7 +51,7 @@ describe("Favicon", () => {
|
||||
const favicon = new Favicon();
|
||||
const originalLink = window.document.querySelector("link");
|
||||
favicon.badge(123);
|
||||
jest.runAllTimers();
|
||||
vi.runAllTimers();
|
||||
const newLink = window.document.querySelector("link");
|
||||
expect(originalLink).not.toStrictEqual(newLink);
|
||||
});
|
||||
@@ -60,9 +63,9 @@ describe("Favicon", () => {
|
||||
link.href = "favicon.png";
|
||||
head.appendChild(link);
|
||||
|
||||
const spy = jest.spyOn(document, "createElement");
|
||||
const spy = vi.spyOn(document, "createElement");
|
||||
const favicon = new Favicon();
|
||||
jest.runAllTimers();
|
||||
vi.runAllTimers();
|
||||
|
||||
const img = spy.mock.results[0].value;
|
||||
img.onload();
|
||||
@@ -78,9 +81,9 @@ describe("Favicon", () => {
|
||||
link.href = "favicon.png";
|
||||
head.appendChild(link);
|
||||
|
||||
const spy = jest.spyOn(document, "createElement");
|
||||
const spy = vi.spyOn(document, "createElement");
|
||||
const favicon = new Favicon();
|
||||
jest.runAllTimers();
|
||||
vi.runAllTimers();
|
||||
|
||||
const img = spy.mock.results[0].value;
|
||||
img.height = 512;
|
||||
@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { vi } from "vitest";
|
||||
import { vi, expect as viExpect } from "vitest";
|
||||
import { mocked as jestMocked } from "jest-mock";
|
||||
|
||||
export const isJest = typeof jest !== "undefined";
|
||||
@@ -22,4 +22,7 @@ const adapter = {
|
||||
const mocked = adapter.mocked;
|
||||
export { adapter as vi, mocked };
|
||||
|
||||
const _expect = isJest ? (expect as unknown as typeof viExpect) : viExpect;
|
||||
export { _expect as expect };
|
||||
|
||||
export { type Mocked, type MockedObject } from "vitest";
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { mkMessage, type MessageEventProps } from "./test-utils";
|
||||
import { expect } from "../setup/adapter.ts";
|
||||
|
||||
export const makeThreadEvent = ({
|
||||
rootEventId,
|
||||
|
||||
Generated
+14
@@ -1067,6 +1067,9 @@ importers:
|
||||
vitest:
|
||||
specifier: 'catalog:'
|
||||
version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@25.9.3)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6)(jsdom@26.1.0(patch_hash=040623e87b1c8b676c2a705513c0276c0704dd1b23fc3a1bb77cde8128b64b5f))(vite@8.1.3(@types/node@25.9.3)(esbuild@0.27.4)(jiti@2.7.0)(sugarss@5.0.1(postcss@8.5.16))(terser@5.48.0)(yaml@2.8.4))
|
||||
vitest-canvas-mock:
|
||||
specifier: ^1.1.4
|
||||
version: 1.1.4(vitest@4.1.9)
|
||||
web-streams-polyfill:
|
||||
specifier: ^4.0.0
|
||||
version: 4.3.0
|
||||
@@ -13675,6 +13678,11 @@ packages:
|
||||
postcss:
|
||||
optional: true
|
||||
|
||||
vitest-canvas-mock@1.1.4:
|
||||
resolution: {integrity: sha512-4boWHY+STwAxGl1+uwakNNoQky5EjPLC8HuponXNoAscYyT1h/F7RUvTkl4IyF/MiWr3V8Q626je3Iel3eArqA==}
|
||||
peerDependencies:
|
||||
vitest: ^3.0.0 || ^4.0.0
|
||||
|
||||
vitest-plugin-vis@5.1.1:
|
||||
resolution: {integrity: sha512-A/MEvQhDpNAj/5b53GiN139glgWUe0Qh5cDupm25G+06FA/2K85bd3tK+Hi4fTaolNbL5WiLNgnQ8dOL+kC7Pw==}
|
||||
peerDependencies:
|
||||
@@ -27960,6 +27968,12 @@ snapshots:
|
||||
- typescript
|
||||
- universal-cookie
|
||||
|
||||
vitest-canvas-mock@1.1.4(vitest@4.1.9):
|
||||
dependencies:
|
||||
cssfontparser: 1.2.1
|
||||
moo-color: 1.0.3
|
||||
vitest: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@25.9.3)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6)(jsdom@26.1.0(patch_hash=040623e87b1c8b676c2a705513c0276c0704dd1b23fc3a1bb77cde8128b64b5f))(vite@8.1.3(@types/node@25.9.3)(esbuild@0.27.4)(jiti@2.7.0)(sugarss@5.0.1(postcss@8.5.16))(terser@5.48.0)(yaml@2.8.4))
|
||||
|
||||
vitest-plugin-vis@5.1.1(@vitest/browser-playwright@4.1.9)(@vitest/browser@4.1.9)(babel-plugin-macros@3.1.0)(typescript@6.0.3)(vitest@4.1.9):
|
||||
dependencies:
|
||||
'@vitest/browser': 4.1.9(vite@8.1.3(@types/node@25.9.3)(esbuild@0.27.4)(jiti@2.7.0)(sugarss@5.0.1(postcss@8.5.16))(terser@5.48.0)(yaml@2.8.4))(vitest@4.1.9)
|
||||
|
||||
Reference in New Issue
Block a user