From 45234b9c947f4bd3c56d3cc1c2c17b8722cd4d3f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 19 Jun 2026 16:34:18 +0100 Subject: [PATCH] Migrate more jest tests to vitest (#33898) * Migrate more jest tests to vitest * Fix jest config * Fix jest config * Make remaining jest tests type-happy --- apps/web/__mocks__/workerFactoryMock-jest.js | 11 + apps/web/__mocks__/workerFactoryMock.js | 4 +- apps/web/jest.config.ts | 5 +- apps/web/package.json | 1 + .../dispatcher/dispatcher.test.ts} | 24 +- .../indexing/EventIndex.test.ts} | 45 +- .../settings/SettingsStore.test.ts} | 57 +- apps/web/src/settings/SettingsStore.ts | 3 +- .../settings/enums/ImageSize.test.ts} | 4 +- .../settings/watchers/ThemeWatcher.test.tsx} | 12 +- apps/web/src/test/setupTests.ts | 18 +- .../utils/PinningUtils.test.ts} | 52 +- .../utils/Singleflight.test.ts} | 14 +- .../form-test.ts => src/utils/form.test.ts} | 8 +- .../maps-test.ts => src/utils/maps.test.ts} | 4 +- apps/web/src/vector/getconfig.test.ts | 2 - apps/web/test/setup/adapter.ts | 25 + apps/web/test/setup/mocks.ts | 30 +- apps/web/test/setupTests.ts | 2 +- apps/web/test/test-utils/beacon.ts | 6 +- apps/web/test/test-utils/client.ts | 130 ++--- apps/web/test/test-utils/date.ts | 12 +- apps/web/test/test-utils/index.ts | 2 +- apps/web/test/test-utils/platform.ts | 10 +- apps/web/test/test-utils/poll.ts | 2 +- apps/web/test/test-utils/room.ts | 2 +- apps/web/test/test-utils/test-utils.ts | 503 +++++++++--------- apps/web/test/test-utils/utilities.ts | 2 +- .../test/unit-tests/DeviceListener-test.ts | 4 +- apps/web/test/unit-tests/Lifecycle-test.ts | 2 +- apps/web/test/unit-tests/Notifier-test.ts | 4 +- .../components/structures/MatrixChat-test.tsx | 2 +- .../components/structures/auth/Login-test.tsx | 2 +- .../structures/auth/Registration-test.tsx | 2 +- .../views/dialogs/InviteDialog-test.tsx | 2 +- .../views/dialogs/LogoutDialog-test.tsx | 2 +- .../views/dialogs/UserSettingsDialog-test.tsx | 6 +- .../security/ResetIdentityDialog-test.tsx | 2 +- .../views/messages/MVideoBody-test.tsx | 2 +- .../views/messages/TextualBody-test.tsx | 2 +- .../tabs/user/AccountUserSettingsTab-test.tsx | 2 +- .../MediaPreviewAccountSettingsTab-test.tsx | 2 +- .../tabs/user/SessionManagerTab-test.tsx | 2 +- .../views/spaces/SpaceCreateMenu-test.tsx | 2 +- .../toasts/VerificationRequestToast-test.tsx | 2 +- .../modules/ProxiedModuleApi-test.tsx | 2 +- .../unit-tests/stores/OwnBeaconStore-test.ts | 2 +- .../unit-tests/stores/RoomViewStore-test.ts | 4 +- .../test/unit-tests/submit-rageshake-test.ts | 2 +- .../utils/beacon/geolocation-test.ts | 2 +- .../utils/crypto/deviceInfo-test.ts | 2 +- .../unit-tests/utils/leave-behaviour-test.ts | 2 +- .../unit-tests/utils/notifications-test.ts | 2 +- .../utils/permalinks/Permalinks-test.ts | 16 +- .../menus/UserMenuViewModel-test.ts | 2 +- .../UrlPreviewGroupViewModel-test.ts | 2 +- .../viewmodels/room/RoomStatusBar-test.ts | 2 +- .../test/viewmodels/room/WidgetPip-test.ts | 2 +- apps/web/tsconfig.json | 4 +- apps/web/vitest.config.ts | 28 + pnpm-lock.yaml | 6 + pnpm-workspace.yaml | 1 + 62 files changed, 625 insertions(+), 488 deletions(-) create mode 100644 apps/web/__mocks__/workerFactoryMock-jest.js rename apps/web/{test/unit-tests/dispatcher/dispatcher-test.ts => src/dispatcher/dispatcher.test.ts} (80%) rename apps/web/{test/unit-tests/indexing/EventIndex-test.ts => src/indexing/EventIndex.test.ts} (84%) rename apps/web/{test/unit-tests/settings/SettingsStore-test.ts => src/settings/SettingsStore.test.ts} (78%) rename apps/web/{test/unit-tests/settings/enums/ImageSize-test.ts => src/settings/enums/ImageSize.test.ts} (93%) rename apps/web/{test/unit-tests/settings/watchers/ThemeWatcher-test.tsx => src/settings/watchers/ThemeWatcher.test.tsx} (96%) rename apps/web/{test/unit-tests/utils/PinningUtils-test.ts => src/utils/PinningUtils.test.ts} (89%) rename apps/web/{test/unit-tests/utils/Singleflight-test.ts => src/utils/Singleflight.test.ts} (90%) rename apps/web/{test/unit-tests/utils/form-test.ts => src/utils/form.test.ts} (68%) rename apps/web/{test/unit-tests/utils/maps-test.ts => src/utils/maps.test.ts} (98%) create mode 100644 apps/web/test/setup/adapter.ts diff --git a/apps/web/__mocks__/workerFactoryMock-jest.js b/apps/web/__mocks__/workerFactoryMock-jest.js new file mode 100644 index 0000000000..a6f04ce086 --- /dev/null +++ b/apps/web/__mocks__/workerFactoryMock-jest.js @@ -0,0 +1,11 @@ +/* +Copyright 2024 New Vector Ltd. +Copyright 2023 The Matrix.org Foundation C.I.C. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +export default function workerFactory(options) { + return jest.fn; +} diff --git a/apps/web/__mocks__/workerFactoryMock.js b/apps/web/__mocks__/workerFactoryMock.js index a6f04ce086..34ff72b12e 100644 --- a/apps/web/__mocks__/workerFactoryMock.js +++ b/apps/web/__mocks__/workerFactoryMock.js @@ -6,6 +6,8 @@ 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"; + export default function workerFactory(options) { - return jest.fn; + return vi.fn; } diff --git a/apps/web/jest.config.ts b/apps/web/jest.config.ts index 8baea77554..c0ef023b18 100644 --- a/apps/web/jest.config.ts +++ b/apps/web/jest.config.ts @@ -41,10 +41,13 @@ const config: Config = { "decoderWorker\\.min\\.wasm": "/__mocks__/empty.js", "waveWorker\\.min\\.js": "/__mocks__/empty.js", "context-filter-polyfill": "/__mocks__/empty.js", - "workers/(.+)Factory": "/__mocks__/workerFactoryMock.js", + "workers/(.+)Factory": "/__mocks__/workerFactoryMock-jest.js", ".*\\?raw": "jest-raw-loader", "recorderWorkletFactory": "/__mocks__/empty.js", "@vector-im/compound-web": "/node_modules/@vector-im/compound-web", + "^vitest$": "/__mocks__/empty.js", + "jest-mock-vitest-adapter": "/test/setup/adapter.ts", + "test-utils-rtl": "/test/test-utils/jest-matrix-react.tsx", }, transformIgnorePatterns: [ `${path.join(__dirname, "../..")}/node_modules/.pnpm/(?!(mime|uuid|p-retry|is-network-error|react-merge-refs|is-ip|ip-regex|super-regex|function-timeout|time-span|convert-hrtime|clone-regexp|is-regexp|matrix-web-i18n|await-lock|@element-hq/web-shared-components|react-virtuoso|lodash|domutils|domhandler|domelementtype|dom-serializer|entities)).+$`, diff --git a/apps/web/package.json b/apps/web/package.json index ebff6e11fb..2cce02de56 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -168,6 +168,7 @@ "@types/ua-parser-js": "^0.7.36", "@typescript-eslint/eslint-plugin": "^8.19.0", "@typescript-eslint/parser": "^8.19.0", + "@vitest/spy": "catalog:", "babel-jest": "^30.0.0", "babel-loader": "^10.0.0", "babel-plugin-jsx-remove-data-test-id": "^3.0.0", diff --git a/apps/web/test/unit-tests/dispatcher/dispatcher-test.ts b/apps/web/src/dispatcher/dispatcher.test.ts similarity index 80% rename from apps/web/test/unit-tests/dispatcher/dispatcher-test.ts rename to apps/web/src/dispatcher/dispatcher.test.ts index 4b8fc31d28..b0a50efbbd 100644 --- a/apps/web/test/unit-tests/dispatcher/dispatcher-test.ts +++ b/apps/web/src/dispatcher/dispatcher.test.ts @@ -6,9 +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 defaultDispatcher from "../../../src/dispatcher/dispatcher"; -import { Action } from "../../../src/dispatcher/actions"; -import { AsyncActionPayload } from "../../../src/dispatcher/payloads"; +// @vitest-environment happy-dom + +import { vi, describe, it, expect } from "vitest"; + +import defaultDispatcher from "./dispatcher"; +import { Action } from "./actions"; +import { AsyncActionPayload } from "./payloads"; describe("MatrixDispatcher", () => { it("should throw error if unregistering unknown token", () => { @@ -21,8 +25,8 @@ describe("MatrixDispatcher", () => { const deferred1 = Promise.withResolvers(); const deferred2 = Promise.withResolvers(); - const fn1 = jest.fn(() => deferred1.resolve(1)); - const fn2 = jest.fn(() => deferred2.resolve(2)); + const fn1 = vi.fn(() => deferred1.resolve(1)); + const fn2 = vi.fn(() => deferred2.resolve(2)); defaultDispatcher.register(fn1); defaultDispatcher.register(fn2); @@ -37,8 +41,8 @@ describe("MatrixDispatcher", () => { const deferred1 = Promise.withResolvers(); const deferred2 = Promise.withResolvers(); - const fn1 = jest.fn(() => deferred1.resolve(1)); - const fn2 = jest.fn(() => deferred2.resolve(2)); + const fn1 = vi.fn(() => deferred1.resolve(1)); + const fn2 = vi.fn(() => deferred2.resolve(2)); defaultDispatcher.register(() => { defaultDispatcher.waitFor([id2]); @@ -53,7 +57,7 @@ describe("MatrixDispatcher", () => { }); it("should not fire callback which was added during a dispatch", () => { - const fn2 = jest.fn(); + const fn2 = vi.fn(); defaultDispatcher.register(() => { defaultDispatcher.register(fn2); @@ -65,10 +69,10 @@ describe("MatrixDispatcher", () => { }); it("should handle AsyncActionPayload", () => { - const fn = jest.fn(); + const fn = vi.fn(); defaultDispatcher.register(fn); - const readyFn = jest.fn((dispatch) => { + const readyFn = vi.fn((dispatch) => { dispatch({ action: "test" }); }); defaultDispatcher.dispatch(new AsyncActionPayload(readyFn), true); diff --git a/apps/web/test/unit-tests/indexing/EventIndex-test.ts b/apps/web/src/indexing/EventIndex.test.ts similarity index 84% rename from apps/web/test/unit-tests/indexing/EventIndex-test.ts rename to apps/web/src/indexing/EventIndex.test.ts index 3e33beaf3b..3b284cd076 100644 --- a/apps/web/test/unit-tests/indexing/EventIndex-test.ts +++ b/apps/web/src/indexing/EventIndex.test.ts @@ -14,7 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { type Mocked } from "jest-mock"; +// @vitest-environment happy-dom + +import { vi, describe, it, expect, afterEach, type Mocked } from "vitest"; import { Direction, type MatrixClient, @@ -25,22 +27,27 @@ import { SyncState, } from "matrix-js-sdk/src/matrix"; -import EventIndex from "../../../src/indexing/EventIndex.ts"; -import { emitPromise, getMockClientWithEventEmitter, mockClientMethodsRooms, mockPlatformPeg } from "../../test-utils"; -import type BaseEventIndexManager from "../../../src/indexing/BaseEventIndexManager.ts"; -import { type ICrawlerCheckpoint } from "../../../src/indexing/BaseEventIndexManager.ts"; -import SettingsStore from "../../../src/settings/SettingsStore.ts"; +import EventIndex from "./EventIndex.ts"; +import { + emitPromise, + getMockClientWithEventEmitter, + mockClientMethodsRooms, + mockPlatformPeg, +} from "../../test/test-utils"; +import type BaseEventIndexManager from "./BaseEventIndexManager.ts"; +import { type ICrawlerCheckpoint } from "./BaseEventIndexManager.ts"; +import SettingsStore from "../settings/SettingsStore.ts"; afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe("EventIndex", () => { it("crawls through the loaded checkpoints", async () => { const mockIndexingManager = { - loadCheckpoints: jest.fn(), - removeCrawlerCheckpoint: jest.fn(), - isEventIndexEmpty: jest.fn().mockResolvedValue(false), + loadCheckpoints: vi.fn(), + removeCrawlerCheckpoint: vi.fn(), + isEventIndexEmpty: vi.fn().mockResolvedValue(false), } as any as Mocked; mockPlatformPeg({ getEventIndexingManager: () => mockIndexingManager }); @@ -48,11 +55,11 @@ describe("EventIndex", () => { const room2 = { roomId: "!room2:id" } as any as Room; const mockClient = getMockClientWithEventEmitter({ getEventMapper: () => (obj: Partial) => new MatrixEvent(obj), - createMessagesRequest: jest.fn(), + createMessagesRequest: vi.fn(), ...mockClientMethodsRooms([room1, room2]), }); - jest.spyOn(SettingsStore, "getValueAt").mockImplementation((_level, settingName): any => { + vi.spyOn(SettingsStore, "getValueAt").mockImplementation((_level, settingName): any => { if (settingName === "crawlerSleepTime") return 0; return undefined; }); @@ -90,11 +97,11 @@ describe("EventIndex", () => { it("adds checkpoints for the encrypted rooms after the first sync", async () => { const mockIndexingManager = { - loadCheckpoints: jest.fn().mockResolvedValue([]), - isEventIndexEmpty: jest.fn().mockResolvedValue(true), - addCrawlerCheckpoint: jest.fn(), - removeCrawlerCheckpoint: jest.fn(), - commitLiveEvents: jest.fn(), + loadCheckpoints: vi.fn().mockResolvedValue([]), + isEventIndexEmpty: vi.fn().mockResolvedValue(true), + addCrawlerCheckpoint: vi.fn(), + removeCrawlerCheckpoint: vi.fn(), + commitLiveEvents: vi.fn(), } as any as Mocked; mockPlatformPeg({ getEventIndexingManager: () => mockIndexingManager }); @@ -111,11 +118,11 @@ describe("EventIndex", () => { }), } as any as Room; const mockCrypto = { - isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(true), + isEncryptionEnabledInRoom: vi.fn().mockResolvedValue(true), }; const mockClient = getMockClientWithEventEmitter({ getEventMapper: () => (obj: Partial) => new MatrixEvent(obj), - createMessagesRequest: jest.fn(), + createMessagesRequest: vi.fn(), getCrypto: () => mockCrypto as any, ...mockClientMethodsRooms([room1, room2]), }); diff --git a/apps/web/test/unit-tests/settings/SettingsStore-test.ts b/apps/web/src/settings/SettingsStore.test.ts similarity index 78% rename from apps/web/test/unit-tests/settings/SettingsStore-test.ts rename to apps/web/src/settings/SettingsStore.test.ts index 2452456bf0..d5f655c7cb 100644 --- a/apps/web/test/unit-tests/settings/SettingsStore-test.ts +++ b/apps/web/src/settings/SettingsStore.test.ts @@ -6,16 +6,19 @@ 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 { ClientEvent, type MatrixClient, type Room, SyncState } from "matrix-js-sdk/src/matrix"; -import { waitFor } from "jest-matrix-react"; +// @vitest-environment happy-dom -import type BasePlatform from "../../../src/BasePlatform"; -import SdkConfig from "../../../src/SdkConfig"; -import { SettingLevel } from "../../../src/settings/SettingLevel"; -import SettingsStore from "../../../src/settings/SettingsStore"; -import { mkStubRoom, mockPlatformPeg, stubClient } from "../../test-utils"; -import { SETTINGS, type SettingKey } from "../../../src/settings/Settings.tsx"; -import MatrixClientBackedController from "../../../src/settings/controllers/MatrixClientBackedController.ts"; +import { vi, describe, it, expect, beforeAll, beforeEach, afterEach } from "vitest"; +import { ClientEvent, type MatrixClient, type Room, SyncState } from "matrix-js-sdk/src/matrix"; +import { waitFor } from "test-utils-rtl"; + +import type BasePlatform from "../BasePlatform"; +import SdkConfig from "../SdkConfig"; +import { SettingLevel } from "./SettingLevel"; +import SettingsStore from "./SettingsStore"; +import { mkStubRoom, mockPlatformPeg, stubClient } from "../../test/test-utils"; +import { SETTINGS, type SettingKey } from "./Settings.tsx"; +import MatrixClientBackedController from "./controllers/MatrixClientBackedController.ts"; const TEST_DATA = [ { @@ -34,18 +37,18 @@ describe("SettingsStore", () => { let platformSettings: Record; beforeAll(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); platformSettings = {}; mockPlatformPeg({ - isLevelSupported: jest.fn().mockReturnValue(true), - supportsSetting: jest.fn().mockReturnValue(true), - setSettingValue: jest.fn().mockImplementation((settingName: string, value: any) => { + isLevelSupported: vi.fn().mockReturnValue(true), + supportsSetting: vi.fn().mockReturnValue(true), + setSettingValue: vi.fn().mockImplementation((settingName: string, value: any) => { platformSettings[settingName] = value; }), - getSettingValue: jest.fn().mockImplementation((settingName: string) => { + getSettingValue: vi.fn().mockImplementation((settingName: string) => { return platformSettings[settingName]; }), - reload: jest.fn(), + reload: vi.fn(), } as unknown as BasePlatform); TEST_DATA.forEach((d) => { @@ -100,21 +103,21 @@ describe("SettingsStore", () => { beforeEach(() => { client = stubClient(); room = mkStubRoom("!room:example.org", "Room", client); - client.getRooms = jest.fn().mockReturnValue([room]); - client.getRoom = jest.fn().mockReturnValue(room); + client.getRooms = vi.fn().mockReturnValue([room]); + client.getRoom = vi.fn().mockReturnValue(room); }); afterEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); describe("Migrate media preview configuration", () => { beforeEach(() => { MatrixClientBackedController.matrixClient = client; - client.getAccountData = jest.fn().mockImplementation((type) => { + client.getAccountData = vi.fn().mockImplementation((type) => { if (type === "im.vector.web.settings") { return { - getContent: jest.fn().mockReturnValue({ + getContent: vi.fn().mockReturnValue({ showImages: false, showAvatarsOnInvites: false, }), @@ -126,7 +129,7 @@ describe("SettingsStore", () => { }); it("migrates media preview configuration immediately", async () => { - client.setAccountData = jest.fn(); + client.setAccountData = vi.fn(); SettingsStore.runMigrations(false); expect(client.setAccountData).toHaveBeenCalledWith("io.element.msc4278.media_preview_config", { invite_avatars: "off", @@ -134,13 +137,13 @@ describe("SettingsStore", () => { }); }); it("migrates media preview configuration once client is ready", async () => { - client.setAccountData = jest.fn(); - const mockInitialSync = (client.isInitialSyncComplete = jest.fn().mockReturnValue(false)); + client.setAccountData = vi.fn(); + const mockInitialSync = (client.isInitialSyncComplete = vi.fn().mockReturnValue(false)); SettingsStore.runMigrations(false); mockInitialSync.mockReturnValue(true); client.emit(ClientEvent.Sync, SyncState.Prepared, null); // Update is asynchronous - waitFor(() => { + await waitFor(() => { expect(client.setAccountData).toHaveBeenCalledWith("io.element.msc4278.media_preview_config", { invite_avatars: "off", media_previews: "off", @@ -149,15 +152,15 @@ describe("SettingsStore", () => { }); it("does not migrate media preview configuration if the session is fresh", async () => { - client.setAccountData = jest.fn(); + client.setAccountData = vi.fn(); SettingsStore.runMigrations(true); client.emit(ClientEvent.Sync, SyncState.Prepared, null); expect(client.setAccountData).not.toHaveBeenCalled(); }); it("does not migrate media preview configuration if the account data is already set", async () => { - client.setAccountData = jest.fn(); - client.getAccountData = jest.fn().mockReturnValue({}); + client.setAccountData = vi.fn(); + client.getAccountData = vi.fn().mockReturnValue({}); SettingsStore.runMigrations(false); client.emit(ClientEvent.Sync, SyncState.Prepared, null); expect(client.setAccountData).not.toHaveBeenCalled(); diff --git a/apps/web/src/settings/SettingsStore.ts b/apps/web/src/settings/SettingsStore.ts index 10100a1af6..006343be68 100644 --- a/apps/web/src/settings/SettingsStore.ts +++ b/apps/web/src/settings/SettingsStore.ts @@ -10,6 +10,8 @@ Please see LICENSE files in the repository root for full details. import { logger } from "matrix-js-sdk/src/logger"; import { type ReactNode } from "react"; import { ClientEvent } from "matrix-js-sdk/src/matrix"; +// Imports directly from shared-components to avoid an import cycle +import { _t } from "@element-hq/web-shared-components"; import DeviceSettingsHandler from "./handlers/DeviceSettingsHandler"; import RoomDeviceSettingsHandler from "./handlers/RoomDeviceSettingsHandler"; @@ -18,7 +20,6 @@ import RoomAccountSettingsHandler from "./handlers/RoomAccountSettingsHandler"; import AccountSettingsHandler from "./handlers/AccountSettingsHandler"; import RoomSettingsHandler from "./handlers/RoomSettingsHandler"; import ConfigSettingsHandler from "./handlers/ConfigSettingsHandler"; -import { _t } from "../languageHandler"; import dis from "../dispatcher/dispatcher"; import { type IFeature, diff --git a/apps/web/test/unit-tests/settings/enums/ImageSize-test.ts b/apps/web/src/settings/enums/ImageSize.test.ts similarity index 93% rename from apps/web/test/unit-tests/settings/enums/ImageSize-test.ts rename to apps/web/src/settings/enums/ImageSize.test.ts index 0d4990978b..88d651f942 100644 --- a/apps/web/test/unit-tests/settings/enums/ImageSize-test.ts +++ b/apps/web/src/settings/enums/ImageSize.test.ts @@ -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 { ImageSize, suggestedSize } from "../../../../src/settings/enums/ImageSize"; +import { describe, it, expect } from "vitest"; + +import { ImageSize, suggestedSize } from "./ImageSize"; describe("ImageSize", () => { describe("suggestedSize", () => { diff --git a/apps/web/test/unit-tests/settings/watchers/ThemeWatcher-test.tsx b/apps/web/src/settings/watchers/ThemeWatcher.test.tsx similarity index 96% rename from apps/web/test/unit-tests/settings/watchers/ThemeWatcher-test.tsx rename to apps/web/src/settings/watchers/ThemeWatcher.test.tsx index 325b55693c..828becbd88 100644 --- a/apps/web/test/unit-tests/settings/watchers/ThemeWatcher-test.tsx +++ b/apps/web/src/settings/watchers/ThemeWatcher.test.tsx @@ -6,10 +6,14 @@ 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 SettingsStore from "../../../../src/settings/SettingsStore"; -import ThemeWatcher from "../../../../src/settings/watchers/ThemeWatcher"; -import { type SettingLevel } from "../../../../src/settings/SettingLevel"; -import { type SettingKey, type Settings } from "../../../../src/settings/Settings.tsx"; +// @vitest-environment happy-dom + +import { describe, it, expect } from "vitest"; + +import SettingsStore from "../SettingsStore"; +import ThemeWatcher from "./ThemeWatcher"; +import { type SettingLevel } from "../SettingLevel"; +import { type SettingKey, type Settings } from "../Settings.tsx"; function makeMatchMedia(values: any) { class FakeMediaQueryList { diff --git a/apps/web/src/test/setupTests.ts b/apps/web/src/test/setupTests.ts index 566eba93fc..84e2000a1e 100644 --- a/apps/web/src/test/setupTests.ts +++ b/apps/web/src/test/setupTests.ts @@ -5,9 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE files in the repository root for full details. */ -import { beforeEach } from "vitest"; +import { vi, beforeEach } from "vitest"; import fetchMock, { manageFetchMockGlobally } from "@fetch-mock/vitest"; +import { mocks } from "../../test/setup/mocks.ts"; +import SdkConfig, { DEFAULTS } from "../SdkConfig"; + manageFetchMockGlobally(); beforeEach(() => { @@ -16,3 +19,16 @@ beforeEach(() => { fetchMock.catch(404); fetchMock.mockGlobal(); }); + +// set up AudioContext API mock +vi.stubGlobal("AudioContext", function () { + return mocks.AudioContext; +}); + +if (globalThis.window === undefined) { + // We are in a node environment, stub a basic window so singletons work + vi.stubGlobal("window", {}); +} + +// uninitialised SdkConfig causes lots of warnings in console, init with defaults +SdkConfig.put(DEFAULTS); diff --git a/apps/web/test/unit-tests/utils/PinningUtils-test.ts b/apps/web/src/utils/PinningUtils.test.ts similarity index 89% rename from apps/web/test/unit-tests/utils/PinningUtils-test.ts rename to apps/web/src/utils/PinningUtils.test.ts index 38ca05244d..e27933e415 100644 --- a/apps/web/test/unit-tests/utils/PinningUtils-test.ts +++ b/apps/web/src/utils/PinningUtils.test.ts @@ -6,19 +6,21 @@ * Please see LICENSE files in the repository root for full details. */ +// @vitest-environment happy-dom + +import { vi, describe, it, test, expect, beforeEach } from "vitest"; import { EventTimeline, EventType, type IEvent, type MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; -import { mocked } from "jest-mock"; -import { createTestClient } from "../../test-utils"; -import PinningUtils from "../../../src/utils/PinningUtils"; -import SettingsStore from "../../../src/settings/SettingsStore"; -import { isContentActionable } from "../../../src/utils/EventUtils"; -import { ReadPinsEventId } from "../../../src/components/views/right_panel/types"; +import { createTestClient } from "../../test/test-utils"; +import PinningUtils from "./PinningUtils"; +import SettingsStore from "../settings/SettingsStore"; +import { isContentActionable } from "./EventUtils"; +import { ReadPinsEventId } from "../components/views/right_panel/types"; -jest.mock("../../../src/utils/EventUtils", () => { +vi.mock("./EventUtils", () => { return { - isContentActionable: jest.fn(), - canPinEvent: jest.fn(), + isContentActionable: vi.fn(), + canPinEvent: vi.fn(), }; }); @@ -26,7 +28,7 @@ describe("PinningUtils", () => { const roomId = "!room:example.org"; const userId = "@alice:example.org"; - const mockedIsContentActionable = mocked(isContentActionable); + const mockedIsContentActionable = vi.mocked(isContentActionable); let matrixClient: MatrixClient; let room: Room; @@ -52,14 +54,14 @@ describe("PinningUtils", () => { beforeEach(() => { // Enable feature pinning - jest.spyOn(SettingsStore, "getValue").mockReturnValue(true); + vi.spyOn(SettingsStore, "getValue").mockReturnValue(true); mockedIsContentActionable.mockImplementation(() => true); matrixClient = createTestClient(); room = new Room(roomId, matrixClient, userId); - matrixClient.getRoom = jest.fn().mockReturnValue(room); + matrixClient.getRoom = vi.fn().mockReturnValue(room); - jest.spyOn( + vi.spyOn( matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "mayClientSendStateEvent", ).mockReturnValue(true); @@ -96,14 +98,14 @@ describe("PinningUtils", () => { describe("isPinned", () => { test("should return false if no room", () => { - matrixClient.getRoom = jest.fn().mockReturnValue(undefined); + matrixClient.getRoom = vi.fn().mockReturnValue(undefined); const event = makePinEvent(); expect(PinningUtils.isPinned(matrixClient, event)).toBe(false); }); test("should return false if no pinned event", () => { - jest.spyOn( + vi.spyOn( matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "getStateEvents", ).mockReturnValue(null); @@ -113,7 +115,7 @@ describe("PinningUtils", () => { }); test("should return false if pinned events do not contain the event id", () => { - jest.spyOn( + vi.spyOn( matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "getStateEvents", ).mockReturnValue({ @@ -127,7 +129,7 @@ describe("PinningUtils", () => { test("should return true if pinned events contains the event id", () => { const event = makePinEvent(); - jest.spyOn( + vi.spyOn( matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "getStateEvents", ).mockReturnValue({ @@ -149,14 +151,14 @@ describe("PinningUtils", () => { }); test("should return false if no room", () => { - matrixClient.getRoom = jest.fn().mockReturnValue(undefined); + matrixClient.getRoom = vi.fn().mockReturnValue(undefined); const event = makePinEvent(); expect(PinningUtils.canPin(matrixClient, event)).toBe(false); }); test("should return false if client cannot send state event", () => { - jest.spyOn( + vi.spyOn( matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "mayClientSendStateEvent", ).mockReturnValue(false); @@ -201,7 +203,7 @@ describe("PinningUtils", () => { describe("pinOrUnpinEvent", () => { test("should do nothing if no room", async () => { - matrixClient.getRoom = jest.fn().mockReturnValue(undefined); + matrixClient.getRoom = vi.fn().mockReturnValue(undefined); const event = makePinEvent(); await PinningUtils.pinOrUnpinEvent(matrixClient, event); @@ -216,7 +218,7 @@ describe("PinningUtils", () => { }); test("should pin the event if not pinned", async () => { - jest.spyOn( + vi.spyOn( matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "getStateEvents", ).mockReturnValue({ @@ -224,8 +226,8 @@ describe("PinningUtils", () => { getContent: () => ({ pinned: ["$otherEventId"] }), }); - jest.spyOn(room, "getAccountData").mockReturnValue({ - getContent: jest.fn().mockReturnValue({ + vi.spyOn(room, "getAccountData").mockReturnValue({ + getContent: vi.fn().mockReturnValue({ event_ids: ["$otherEventId"], }), } as unknown as MatrixEvent); @@ -247,7 +249,7 @@ describe("PinningUtils", () => { test("should unpin the event if already pinned", async () => { const event = makePinEvent(); - jest.spyOn( + vi.spyOn( matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "getStateEvents", ).mockReturnValue({ @@ -271,7 +273,7 @@ describe("PinningUtils", () => { }); test("should return false if client cannot send state event", () => { - jest.spyOn( + vi.spyOn( matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!, "mayClientSendStateEvent", ).mockReturnValue(false); diff --git a/apps/web/test/unit-tests/utils/Singleflight-test.ts b/apps/web/src/utils/Singleflight.test.ts similarity index 90% rename from apps/web/test/unit-tests/utils/Singleflight-test.ts rename to apps/web/src/utils/Singleflight.test.ts index 58e15f2060..c816189c43 100644 --- a/apps/web/test/unit-tests/utils/Singleflight-test.ts +++ b/apps/web/src/utils/Singleflight.test.ts @@ -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 { Singleflight } from "../../../src/utils/Singleflight"; +import { vi, describe, it, expect, afterEach } from "vitest"; + +import { Singleflight } from "./Singleflight"; describe("Singleflight", () => { afterEach(() => { @@ -28,7 +30,7 @@ describe("Singleflight", () => { const instance = {}; const key = "test"; const val = {}; // unique object for reference check - const fn = jest.fn().mockReturnValue(val); + const fn = vi.fn().mockReturnValue(val); const sf = Singleflight.for(instance, key); const r1 = sf.do(fn); expect(r1).toBe(val); @@ -42,7 +44,7 @@ describe("Singleflight", () => { const instance = {}; const key = "test"; const val = {}; // unique object for reference check - const fn = jest.fn().mockReturnValue(val); + const fn = vi.fn().mockReturnValue(val); let sf = Singleflight.for(instance, key); const r1 = sf.do(fn); expect(r1).toBe(val); @@ -57,7 +59,7 @@ describe("Singleflight", () => { const instance = {}; const key = "test"; const val = {}; // unique object for reference check - const fn = jest.fn().mockReturnValue(val); + const fn = vi.fn().mockReturnValue(val); const sf = Singleflight.for(instance, key); const r1 = sf.do(fn); expect(r1).toBe(val); @@ -72,7 +74,7 @@ describe("Singleflight", () => { const instance = {}; const key = "test"; const val = {}; // unique object for reference check - const fn = jest.fn().mockReturnValue(val); + const fn = vi.fn().mockReturnValue(val); const sf = Singleflight.for(instance, key); const r1 = sf.do(fn); expect(r1).toBe(val); @@ -87,7 +89,7 @@ describe("Singleflight", () => { const instance = {}; const key = "test"; const val = {}; // unique object for reference check - const fn = jest.fn().mockReturnValue(val); + const fn = vi.fn().mockReturnValue(val); const sf = Singleflight.for(instance, key); const r1 = sf.do(fn); expect(r1).toBe(val); diff --git a/apps/web/test/unit-tests/utils/form-test.ts b/apps/web/src/utils/form.test.ts similarity index 68% rename from apps/web/test/unit-tests/utils/form-test.ts rename to apps/web/src/utils/form.test.ts index d1036e146f..030522b856 100644 --- a/apps/web/test/unit-tests/utils/form-test.ts +++ b/apps/web/src/utils/form.test.ts @@ -5,12 +5,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 { onSubmitPreventDefault } from "../../../src/utils/form.ts"; +// @vitest-environment happy-dom + +import { vi, describe, it, expect } from "vitest"; + +import { onSubmitPreventDefault } from "./form.ts"; describe("onSubmitPreventDefault", () => { it("should preventDefault", () => { const event = new SubmitEvent("submit"); - const spy = jest.spyOn(event, "preventDefault"); + const spy = vi.spyOn(event, "preventDefault"); onSubmitPreventDefault(event); expect(spy).toHaveBeenCalled(); diff --git a/apps/web/test/unit-tests/utils/maps-test.ts b/apps/web/src/utils/maps.test.ts similarity index 98% rename from apps/web/test/unit-tests/utils/maps-test.ts rename to apps/web/src/utils/maps.test.ts index 619766e679..4fe4174197 100644 --- a/apps/web/test/unit-tests/utils/maps-test.ts +++ b/apps/web/src/utils/maps.test.ts @@ -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 { EnhancedMap, mapDiff } from "../../../src/utils/maps"; +import { describe, it, expect } from "vitest"; + +import { EnhancedMap, mapDiff } from "./maps"; describe("maps", () => { describe("mapDiff", () => { diff --git a/apps/web/src/vector/getconfig.test.ts b/apps/web/src/vector/getconfig.test.ts index b555c497e3..c0f1241bd6 100644 --- a/apps/web/src/vector/getconfig.test.ts +++ b/apps/web/src/vector/getconfig.test.ts @@ -6,8 +6,6 @@ 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, afterAll } from "vitest"; import fetchMock from "@fetch-mock/vitest"; diff --git a/apps/web/test/setup/adapter.ts b/apps/web/test/setup/adapter.ts new file mode 100644 index 0000000000..13d892bac3 --- /dev/null +++ b/apps/web/test/setup/adapter.ts @@ -0,0 +1,25 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +import { vi } from "vitest"; +import { mocked as jestMocked } from "jest-mock"; + +const isJest = typeof jest !== "undefined"; + +/** + * Subset of the vitest API surface, with jest equivalents for the same functions when running under jest. + */ +const adapter = { + fn: isJest ? (jest.fn as unknown as typeof vi.fn) : vi.fn, + spyOn: isJest ? (jest.spyOn as unknown as typeof vi.spyOn) : vi.spyOn, + mocked: isJest ? (jestMocked as typeof vi.mocked) : vi.mocked, +} as Pick; + +const mocked = adapter.mocked; +export { adapter as vi, mocked }; + +export { type Mocked, type MockedObject } from "vitest"; diff --git a/apps/web/test/setup/mocks.ts b/apps/web/test/setup/mocks.ts index d98991c568..27028742a2 100644 --- a/apps/web/test/setup/mocks.ts +++ b/apps/web/test/setup/mocks.ts @@ -6,23 +6,25 @@ 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 "./adapter.ts"; + export const mocks = { AudioBufferSourceNode: { - connect: jest.fn(), - start: jest.fn(), - stop: jest.fn(), + connect: vi.fn(), + start: vi.fn(), + stop: vi.fn(), } as unknown as AudioBufferSourceNode, AudioContext: { - close: jest.fn(), - createMediaElementSource: jest.fn(), - createMediaStreamDestination: jest.fn(), - createMediaStreamSource: jest.fn(), - createStreamTrackSource: jest.fn(), - createBufferSource: jest.fn((): AudioBufferSourceNode => ({ ...mocks.AudioBufferSourceNode })), - getOutputTimestamp: jest.fn(), - resume: jest.fn(), - setSinkId: jest.fn(), - suspend: jest.fn(), - decodeAudioData: jest.fn(), + close: vi.fn(), + createMediaElementSource: vi.fn(), + createMediaStreamDestination: vi.fn(), + createMediaStreamSource: vi.fn(), + createStreamTrackSource: vi.fn(), + createBufferSource: vi.fn((): AudioBufferSourceNode => ({ ...mocks.AudioBufferSourceNode })), + getOutputTimestamp: vi.fn(), + resume: vi.fn(), + setSinkId: vi.fn(), + suspend: vi.fn(), + decodeAudioData: vi.fn(), } as unknown as AudioContext, }; diff --git a/apps/web/test/setupTests.ts b/apps/web/test/setupTests.ts index bcfede9805..10079fa141 100644 --- a/apps/web/test/setupTests.ts +++ b/apps/web/test/setupTests.ts @@ -10,7 +10,7 @@ import { env } from "process"; import "@testing-library/jest-dom"; import "blob-polyfill"; import { secureRandomString } from "matrix-js-sdk/src/randomstring"; -import { mocked } from "jest-mock"; +import { mocked } from "jest-mock-vitest-adapter"; import { PredictableRandom } from "./test-utils/predictableRandom"; import * as rageshake from "../src/rageshake/rageshake"; diff --git a/apps/web/test/test-utils/beacon.ts b/apps/web/test/test-utils/beacon.ts index 2688d223ad..71e748926c 100644 --- a/apps/web/test/test-utils/beacon.ts +++ b/apps/web/test/test-utils/beacon.ts @@ -6,7 +6,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 { type MockedObject } from "jest-mock"; +import { type MockedObject } from "jest-mock-vitest-adapter"; import { type MatrixClient, MatrixEvent, @@ -165,7 +165,7 @@ export const mockGeolocation = (): MockedObject => { * See for error codes: https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError */ export const watchPositionMockImplementation = (delays: number[], errorCodes: number[] = []) => { - return (callback: PositionCallback, error: PositionErrorCallback): number => { + return (callback: PositionCallback, error?: PositionErrorCallback | null): number => { const position = makeGeolocationPosition({}); let totalDelay = 0; @@ -173,7 +173,7 @@ export const watchPositionMockImplementation = (delays: number[], errorCodes: nu totalDelay += delayMs; const timeout = window.setTimeout(() => { if (errorCodes[index]) { - error(getMockGeolocationPositionError(errorCodes[index], "error message")); + error?.(getMockGeolocationPositionError(errorCodes[index], "error message")); } else { callback({ ...position, timestamp: position.timestamp + totalDelay }); } diff --git a/apps/web/test/test-utils/client.ts b/apps/web/test/test-utils/client.ts index b54951ce42..a700a09d25 100644 --- a/apps/web/test/test-utils/client.ts +++ b/apps/web/test/test-utils/client.ts @@ -7,11 +7,14 @@ Please see LICENSE files in the repository root for full details. */ import EventEmitter from "events"; -import { type MethodLikeKeys, mocked, type MockedObject, type PropertyLikeKeys } from "jest-mock"; +import { type MockedObject } from "vitest"; +import { type MethodLikeKeys, type PropertyLikeKeys } from "jest-mock"; +import { type MockedObjectDeep } from "@vitest/spy"; import { Feature, ServerSupport } from "matrix-js-sdk/src/feature"; import { type MatrixClient, type Room, User } from "matrix-js-sdk/src/matrix"; import { MatrixClientPeg } from "../../src/MatrixClientPeg"; +import { vi } from "../setup/adapter.ts"; /** * Mocked generic class with a real EventEmitter. @@ -53,7 +56,7 @@ export class MockClientWithEventEmitter extends EventEmitter { * eg * ``` * const mockClient = getMockClientWithEventEmitter({ - getUserId: jest.fn().mockReturnValue(aliceId), + getUserId: vi.fn().mockReturnValue(aliceId), }); * ``` * @@ -62,10 +65,10 @@ export class MockClientWithEventEmitter extends EventEmitter { export const getMockClientWithEventEmitter = ( mockProperties: Partial>, ): MockedObject => { - const mock = mocked(new MockClientWithEventEmitter(mockProperties) as unknown as MatrixClient); + const mock = vi.mocked(new MockClientWithEventEmitter(mockProperties) as unknown as MatrixClient); - jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mock); - jest.spyOn(MatrixClientPeg, "safeGet").mockReturnValue(mock); + vi.spyOn(MatrixClientPeg, "get").mockReturnValue(mock); + vi.spyOn(MatrixClientPeg, "safeGet").mockReturnValue(mock); // @ts-ignore simplified test stub mock.canSupport = new Map(); @@ -76,8 +79,8 @@ export const getMockClientWithEventEmitter = ( }; export const unmockClientPeg = () => { - jest.spyOn(MatrixClientPeg, "get").mockRestore(); - jest.spyOn(MatrixClientPeg, "safeGet").mockRestore(); + vi.spyOn(MatrixClientPeg, "get").mockRestore(); + vi.spyOn(MatrixClientPeg, "safeGet").mockRestore(); }; /** @@ -88,19 +91,20 @@ export const unmockClientPeg = () => { }); * ``` */ -export const mockClientMethodsUser = (userId = "@alice:domain") => ({ - getUserId: jest.fn().mockReturnValue(userId), - getDomain: jest.fn().mockReturnValue(userId.split(":")[1]), - getSafeUserId: jest.fn().mockReturnValue(userId), - getUser: jest.fn().mockReturnValue(new User(userId)), - isGuest: jest.fn().mockReturnValue(false), - mxcUrlToHttp: jest.fn().mockReturnValue("mock-mxcUrlToHttp"), - credentials: { userId }, - getThreePids: jest.fn().mockResolvedValue({ threepids: [] }), - getAccessToken: jest.fn(), - getDeviceId: jest.fn(), - getAccountData: jest.fn(), -}); +export const mockClientMethodsUser = (userId = "@alice:domain") => + ({ + getUserId: vi.fn().mockReturnValue(userId), + getDomain: vi.fn().mockReturnValue(userId.split(":")[1]), + getSafeUserId: vi.fn().mockReturnValue(userId), + getUser: vi.fn().mockReturnValue(new User(userId)), + isGuest: vi.fn().mockReturnValue(false), + mxcUrlToHttp: vi.fn().mockReturnValue("mock-mxcUrlToHttp"), + credentials: { userId }, + getThreePids: vi.fn().mockResolvedValue({ threepids: [] }), + getAccessToken: vi.fn(), + getDeviceId: vi.fn(), + getAccountData: vi.fn(), + }) satisfies MockedObjectDeep; /** * Returns basic mocked client methods related to rendering events @@ -110,58 +114,60 @@ export const mockClientMethodsUser = (userId = "@alice:domain") => ({ }); * ``` */ -export const mockClientMethodsEvents = () => ({ - decryptEventIfNeeded: jest.fn(), - getPushActionsForEvent: jest.fn(), -}); +export const mockClientMethodsEvents = () => + ({ + decryptEventIfNeeded: vi.fn(), + getPushActionsForEvent: vi.fn(), + }) satisfies MockedObjectDeep; /** * Returns basic mocked pushProcessor */ -export const mockClientPushProcessor = () => ({ - pushProcessor: { - getPushRuleById: jest.fn(), - ruleMatchesEvent: jest.fn(), - }, -}); +export const mockClientPushProcessor = () => + ({ + pushProcessor: { + getPushRuleById: vi.fn(), + ruleMatchesEvent: vi.fn(), + }, + }) satisfies MockedObjectDeep; /** * Returns basic mocked client methods related to server support */ export const mockClientMethodsServer = (): Partial, unknown>> => ({ - getIdentityServerUrl: jest.fn(), - getHomeserverUrl: jest.fn(), - getCapabilities: jest.fn().mockResolvedValue({}), - getCachedCapabilities: jest.fn().mockResolvedValue({}), - getClientWellKnown: jest.fn().mockReturnValue({}), - waitForClientWellKnown: jest.fn().mockResolvedValue({}), - doesServerSupportUnstableFeature: jest.fn().mockResolvedValue(false), - isVersionSupported: jest.fn().mockResolvedValue(false), - getVersions: jest.fn().mockResolvedValue({}), - isFallbackICEServerAllowed: jest.fn(), + getIdentityServerUrl: vi.fn(), + getHomeserverUrl: vi.fn(), + getCapabilities: vi.fn().mockResolvedValue({}), + getCachedCapabilities: vi.fn().mockResolvedValue({}), + getClientWellKnown: vi.fn().mockReturnValue({}), + waitForClientWellKnown: vi.fn().mockResolvedValue({}), + doesServerSupportUnstableFeature: vi.fn().mockResolvedValue(false), + isVersionSupported: vi.fn().mockResolvedValue(false), + getVersions: vi.fn().mockResolvedValue({}), + isFallbackICEServerAllowed: vi.fn(), }); export const mockClientMethodsDevice = ( deviceId = "test-device-id", ): Partial, unknown>> => ({ - getDeviceId: jest.fn().mockReturnValue(deviceId), - getDevices: jest.fn().mockResolvedValue({ devices: [] }), + getDeviceId: vi.fn().mockReturnValue(deviceId), + getDevices: vi.fn().mockResolvedValue({ devices: [] }), }); export const mockClientMethodsCrypto = (): Partial< Record & PropertyLikeKeys, unknown> > => ({ - isKeyBackupKeyStored: jest.fn(), - getCrossSigningCacheCallbacks: jest.fn().mockReturnValue({ getCrossSigningKeyCache: jest.fn() }), + isKeyBackupKeyStored: vi.fn(), + getCrossSigningCacheCallbacks: vi.fn().mockReturnValue({ getCrossSigningKeyCache: vi.fn() }), secretStorage: { - hasKey: jest.fn(), - isStored: jest.fn().mockResolvedValue(null), - getDefaultKeyId: jest.fn().mockResolvedValue(null), + hasKey: vi.fn(), + isStored: vi.fn().mockResolvedValue(null), + getDefaultKeyId: vi.fn().mockResolvedValue(null), }, - getCrypto: jest.fn().mockReturnValue({ - getUserDeviceInfo: jest.fn(), - getDeviceVerificationStatus: jest.fn().mockResolvedValue(null), - getCrossSigningStatus: jest.fn().mockResolvedValue({ + getCrypto: vi.fn().mockReturnValue({ + getUserDeviceInfo: vi.fn(), + getDeviceVerificationStatus: vi.fn().mockResolvedValue(null), + getCrossSigningStatus: vi.fn().mockResolvedValue({ publicKeysOnDevice: true, privateKeysInSecretStorage: false, privateKeysCachedLocally: { @@ -170,19 +176,19 @@ export const mockClientMethodsCrypto = (): Partial< userSigningKey: true, }, }), - isCrossSigningReady: jest.fn().mockResolvedValue(true), - isSecretStorageReady: jest.fn(), - getSessionBackupPrivateKey: jest.fn(), - getVersion: jest.fn().mockReturnValue("Version 0"), - getOwnDeviceKeys: jest.fn().mockReturnValue(new Promise(() => {})), - getCrossSigningKeyId: jest.fn(), - isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false), - getKeyBackupInfo: jest.fn().mockResolvedValue(null), + isCrossSigningReady: vi.fn().mockResolvedValue(true), + isSecretStorageReady: vi.fn(), + getSessionBackupPrivateKey: vi.fn(), + getVersion: vi.fn().mockReturnValue("Version 0"), + getOwnDeviceKeys: vi.fn().mockReturnValue(new Promise(() => {})), + getCrossSigningKeyId: vi.fn(), + isEncryptionEnabledInRoom: vi.fn().mockResolvedValue(false), + getKeyBackupInfo: vi.fn().mockResolvedValue(null), }), }); export const mockClientMethodsRooms = (rooms: Room[] = []): Partial, unknown>> => ({ - getRooms: jest.fn().mockReturnValue(rooms), - getRoom: jest.fn((roomId) => rooms.find((r) => r.roomId === roomId) ?? null), - isRoomEncrypted: jest.fn(), + getRooms: vi.fn().mockReturnValue(rooms), + getRoom: vi.fn((roomId) => rooms.find((r) => r.roomId === roomId) ?? null), + isRoomEncrypted: vi.fn(), }); diff --git a/apps/web/test/test-utils/date.ts b/apps/web/test/test-utils/date.ts index b33961e7c1..f22de9e512 100644 --- a/apps/web/test/test-utils/date.ts +++ b/apps/web/test/test-utils/date.ts @@ -6,19 +6,21 @@ 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 "../setup/adapter.ts"; + export const REPEATABLE_DATE = new Date(2022, 10, 17, 16, 58, 32, 517); -const RealDateTimeFormat = global.Intl.DateTimeFormat; +const RealDateTimeFormat = globalThis.Intl.DateTimeFormat; // allow setting default locale and set timezone // defaults to en-GB / Europe/London // so tests run the same everywhere export const mockIntlDateTimeFormat = (defaultLocale = "en-GB", defaultTimezone = "Europe/London"): void => { - jest.spyOn(global.Intl, "DateTimeFormat").mockImplementation( - (locale, options) => new RealDateTimeFormat(locale || defaultLocale, { ...options, timeZone: defaultTimezone }), - ); + vi.spyOn(globalThis.Intl, "DateTimeFormat").mockImplementation(function (locale, options) { + return new RealDateTimeFormat(locale || defaultLocale, { ...options, timeZone: defaultTimezone }); + }); }; export const unmockIntlDateTimeFormat = (): void => { - jest.spyOn(global.Intl, "DateTimeFormat").mockRestore(); + vi.spyOn(globalThis.Intl, "DateTimeFormat").mockRestore(); }; diff --git a/apps/web/test/test-utils/index.ts b/apps/web/test/test-utils/index.ts index d1298ca3df..87aeeb98c5 100644 --- a/apps/web/test/test-utils/index.ts +++ b/apps/web/test/test-utils/index.ts @@ -6,7 +6,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 { type RenderResult, screen, waitFor } from "jest-matrix-react"; +import { type RenderResult, screen, waitFor } from "test-utils-rtl"; export * from "./beacon"; export * from "./client"; diff --git a/apps/web/test/test-utils/platform.ts b/apps/web/test/test-utils/platform.ts index ec742a407e..ad109e8462 100644 --- a/apps/web/test/test-utils/platform.ts +++ b/apps/web/test/test-utils/platform.ts @@ -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 { type MethodLikeKeys, mocked, type MockedObject } from "jest-mock"; +import { type MethodLikeKeys } from "jest-mock"; +import { type MockedObject } from "vitest"; import BasePlatform from "../../src/BasePlatform"; import PlatformPeg from "../../src/PlatformPeg"; import * as SessionLock from "../../src/utils/SessionLock"; +import { vi } from "../setup/adapter.ts"; // doesn't implement abstract // @ts-ignore @@ -38,10 +40,10 @@ export const mockPlatformPeg = ( platformMocks: Partial, unknown>> = {}, ): MockedObject => { const mockPlatform = new MockPlatform(platformMocks); - jest.spyOn(PlatformPeg, "get").mockReturnValue(mockPlatform); - return mocked(mockPlatform); + vi.spyOn(PlatformPeg, "get").mockReturnValue(mockPlatform); + return vi.mocked(mockPlatform); }; export const unmockPlatformPeg = () => { - jest.spyOn(PlatformPeg, "get").mockRestore(); + vi.spyOn(PlatformPeg, "get").mockRestore(); }; diff --git a/apps/web/test/test-utils/poll.ts b/apps/web/test/test-utils/poll.ts index a9896c62ca..6ffe2f7aa8 100644 --- a/apps/web/test/test-utils/poll.ts +++ b/apps/web/test/test-utils/poll.ts @@ -6,7 +6,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 { type Mocked } from "jest-mock"; +import { type Mocked } from "jest-mock-vitest-adapter"; import { type MatrixClient, MatrixEvent, diff --git a/apps/web/test/test-utils/room.ts b/apps/web/test/test-utils/room.ts index 8c05e02c05..7008196e41 100644 --- a/apps/web/test/test-utils/room.ts +++ b/apps/web/test/test-utils/room.ts @@ -6,7 +6,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 { type MockedObject } from "jest-mock"; +import { type MockedObject } from "jest-mock-vitest-adapter"; import { type EventTimeline, EventType, type MatrixClient, type MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; diff --git a/apps/web/test/test-utils/test-utils.ts b/apps/web/test/test-utils/test-utils.ts index 473088493d..eb0532bbd9 100644 --- a/apps/web/test/test-utils/test-utils.ts +++ b/apps/web/test/test-utils/test-utils.ts @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import EventEmitter from "events"; -import { mocked, type MockedObject } from "jest-mock"; +import { type MockedObject } from "vitest"; import { MatrixEvent, type Room, @@ -48,6 +48,7 @@ import { type ValidatedServerConfig } from "../../src/utils/ValidatedServerConfi import { EnhancedMap } from "../../src/utils/maps"; import { type AsyncStoreWithClient } from "../../src/stores/AsyncStoreWithClient"; import MatrixClientBackedSettingsHandler from "../../src/settings/handlers/MatrixClientBackedSettingsHandler"; +import { vi } from "../setup/adapter.ts"; /** * Stub out the MatrixClient, and configure the MatrixClientPeg object to @@ -66,10 +67,10 @@ export function stubClient(): MatrixClient { // // 'sandbox.restore()' doesn't work correctly on inherited methods, // so we do this for each method - jest.spyOn(peg, "get"); - jest.spyOn(peg, "safeGet"); - jest.spyOn(peg, "unset"); - jest.spyOn(peg, "replaceUsingCreds"); + vi.spyOn(peg, "get"); + vi.spyOn(peg, "safeGet"); + vi.spyOn(peg, "unset"); + vi.spyOn(peg, "replaceUsingCreds"); // MatrixClientPeg.safeGet() is called a /lot/, so implement it with our own // fast stub function rather than a sinon stub peg.get = () => client; @@ -90,64 +91,64 @@ export function createTestClient(): MatrixClient { let createdRoom: Room | undefined; const client = { - getHomeserverUrl: jest.fn(), - getIdentityServerUrl: jest.fn(), - getDomain: jest.fn().mockReturnValue("matrix.org"), - getUserId: jest.fn().mockReturnValue("@userId:matrix.org"), - getSafeUserId: jest.fn().mockReturnValue("@userId:matrix.org"), - getUserIdLocalpart: jest.fn().mockResolvedValue("userId"), - getUser: jest.fn().mockReturnValue({ on: jest.fn(), off: jest.fn() }), - getDevice: jest.fn(), - getDeviceId: jest.fn().mockReturnValue("ABCDEFGHI"), + getHomeserverUrl: vi.fn(), + getIdentityServerUrl: vi.fn(), + getDomain: vi.fn().mockReturnValue("matrix.org"), + getUserId: vi.fn().mockReturnValue("@userId:matrix.org"), + getSafeUserId: vi.fn().mockReturnValue("@userId:matrix.org"), + getUserIdLocalpart: vi.fn().mockResolvedValue("userId"), + getUser: vi.fn().mockReturnValue({ on: vi.fn(), off: vi.fn() }), + getDevice: vi.fn(), + getDeviceId: vi.fn().mockReturnValue("ABCDEFGHI"), deviceId: "ABCDEFGHI", - getDevices: jest.fn().mockResolvedValue({ devices: [{ device_id: "ABCDEFGHI" }] }), - getSessionId: jest.fn().mockReturnValue("iaszphgvfku"), + getDevices: vi.fn().mockResolvedValue({ devices: [{ device_id: "ABCDEFGHI" }] }), + getSessionId: vi.fn().mockReturnValue("iaszphgvfku"), credentials: { userId: "@userId:matrix.org" }, - getAccessToken: jest.fn(), + getAccessToken: vi.fn(), secretStorage: { - get: jest.fn(), - isStored: jest.fn().mockReturnValue(false), - checkKey: jest.fn().mockResolvedValue(false), - hasKey: jest.fn().mockReturnValue(false), - getDefaultKeyId: jest.fn().mockResolvedValue(null), + get: vi.fn(), + isStored: vi.fn().mockReturnValue(false), + checkKey: vi.fn().mockResolvedValue(false), + hasKey: vi.fn().mockReturnValue(false), + getDefaultKeyId: vi.fn().mockResolvedValue(null), }, store: { - getPendingEvents: jest.fn().mockResolvedValue([]), - setPendingEvents: jest.fn().mockResolvedValue(undefined), - storeRoom: jest.fn(), - removeRoom: jest.fn(), + getPendingEvents: vi.fn().mockResolvedValue([]), + setPendingEvents: vi.fn().mockResolvedValue(undefined), + storeRoom: vi.fn(), + removeRoom: vi.fn(), }, - getCrypto: jest.fn().mockReturnValue({ - getOwnDeviceKeys: jest.fn().mockResolvedValue({ ed25519: "ed25519", curve25519: "curve25519" }), - getUserDeviceInfo: jest.fn().mockResolvedValue(new Map()), - getUserVerificationStatus: jest.fn(), - getDeviceVerificationStatus: jest.fn(), - resetKeyBackup: jest.fn(), - isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false), - isStateEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false), - getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]), - setDeviceIsolationMode: jest.fn(), - prepareToEncrypt: jest.fn(), - bootstrapCrossSigning: jest.fn(), - getActiveSessionBackupVersion: jest.fn().mockResolvedValue(null), - isKeyBackupTrusted: jest.fn().mockResolvedValue({}), - createRecoveryKeyFromPassphrase: jest.fn().mockResolvedValue({ + getCrypto: vi.fn().mockReturnValue({ + getOwnDeviceKeys: vi.fn().mockResolvedValue({ ed25519: "ed25519", curve25519: "curve25519" }), + getUserDeviceInfo: vi.fn().mockResolvedValue(new Map()), + getUserVerificationStatus: vi.fn(), + getDeviceVerificationStatus: vi.fn(), + resetKeyBackup: vi.fn(), + isEncryptionEnabledInRoom: vi.fn().mockResolvedValue(false), + isStateEncryptionEnabledInRoom: vi.fn().mockResolvedValue(false), + getVerificationRequestsToDeviceInProgress: vi.fn().mockReturnValue([]), + setDeviceIsolationMode: vi.fn(), + prepareToEncrypt: vi.fn(), + bootstrapCrossSigning: vi.fn(), + getActiveSessionBackupVersion: vi.fn().mockResolvedValue(null), + isKeyBackupTrusted: vi.fn().mockResolvedValue({}), + createRecoveryKeyFromPassphrase: vi.fn().mockResolvedValue({ privateKey: new Uint8Array(32), encodedPrivateKey: "encoded private key", }), - bootstrapSecretStorage: jest.fn(), - isDehydrationSupported: jest.fn().mockResolvedValue(false), - restoreKeyBackup: jest.fn(), - restoreKeyBackupWithPassphrase: jest.fn(), - loadSessionBackupPrivateKeyFromSecretStorage: jest.fn(), - storeSessionBackupPrivateKey: jest.fn(), - checkKeyBackupAndEnable: jest.fn().mockResolvedValue(null), - getKeyBackupInfo: jest.fn().mockResolvedValue(null), - getEncryptionInfoForEvent: jest.fn().mockResolvedValue(null), - getCrossSigningStatus: jest.fn().mockResolvedValue({ + bootstrapSecretStorage: vi.fn(), + isDehydrationSupported: vi.fn().mockResolvedValue(false), + restoreKeyBackup: vi.fn(), + restoreKeyBackupWithPassphrase: vi.fn(), + loadSessionBackupPrivateKeyFromSecretStorage: vi.fn(), + storeSessionBackupPrivateKey: vi.fn(), + checkKeyBackupAndEnable: vi.fn().mockResolvedValue(null), + getKeyBackupInfo: vi.fn().mockResolvedValue(null), + getEncryptionInfoForEvent: vi.fn().mockResolvedValue(null), + getCrossSigningStatus: vi.fn().mockResolvedValue({ publicKeysOnDevice: false, privateKeysInSecretStorage: false, privateKeysCachedLocally: { @@ -156,17 +157,17 @@ export function createTestClient(): MatrixClient { userSigningKey: false, }, }), - isCrossSigningReady: jest.fn().mockResolvedValue(false), - disableKeyStorage: jest.fn(), - resetEncryption: jest.fn(), - getSessionBackupPrivateKey: jest.fn().mockResolvedValue(null), - isSecretStorageReady: jest.fn().mockResolvedValue(false), - deleteKeyBackupVersion: jest.fn(), - crossSignDevice: jest.fn(), + isCrossSigningReady: vi.fn().mockResolvedValue(false), + disableKeyStorage: vi.fn(), + resetEncryption: vi.fn(), + getSessionBackupPrivateKey: vi.fn().mockResolvedValue(null), + isSecretStorageReady: vi.fn().mockResolvedValue(false), + deleteKeyBackupVersion: vi.fn(), + crossSignDevice: vi.fn(), }), - getPushActionsForEvent: jest.fn(), - getRoom: jest.fn().mockImplementation((roomId) => { + getPushActionsForEvent: vi.fn(), + getRoom: vi.fn().mockImplementation((roomId) => { // If the test called `createRoom`, return the mocked room it created. if (createdRoom) { return createdRoom; @@ -174,32 +175,32 @@ export function createTestClient(): MatrixClient { return mkStubRoom(roomId, "My room", client); } }), - getRooms: jest.fn().mockReturnValue([]), - getVisibleRooms: jest.fn().mockReturnValue([]), - loginFlows: jest.fn(), + getRooms: vi.fn().mockReturnValue([]), + getVisibleRooms: vi.fn().mockReturnValue([]), + loginFlows: vi.fn(), on: eventEmitter.on.bind(eventEmitter), once: eventEmitter.once.bind(eventEmitter), off: eventEmitter.off.bind(eventEmitter), removeListener: eventEmitter.removeListener.bind(eventEmitter), emit: eventEmitter.emit.bind(eventEmitter), - isRoomEncrypted: jest.fn().mockReturnValue(false), - peekInRoom: jest.fn().mockResolvedValue(mkStubRoom(undefined, undefined, undefined)), - stopPeeking: jest.fn(), + isRoomEncrypted: vi.fn().mockReturnValue(false), + peekInRoom: vi.fn().mockResolvedValue(mkStubRoom(undefined, undefined, undefined)), + stopPeeking: vi.fn(), - getEventTimeline: jest.fn().mockResolvedValue([]), - paginateEventTimeline: jest.fn().mockResolvedValue(undefined), - sendReadReceipt: jest.fn().mockResolvedValue(undefined), - getRoomIdForAlias: jest.fn().mockResolvedValue(undefined), - getRoomDirectoryVisibility: jest.fn().mockResolvedValue(undefined), - getProfileInfo: jest.fn().mockResolvedValue({}), - getThirdpartyProtocols: jest.fn().mockResolvedValue({}), - getClientWellKnown: jest.fn().mockReturnValue(null), - waitForClientWellKnown: jest.fn().mockResolvedValue({}), - supportsVoip: jest.fn().mockReturnValue(true), - getTurnServers: jest.fn().mockReturnValue([]), - getTurnServersExpiry: jest.fn().mockReturnValue(2 ^ 32), - getThirdpartyUser: jest.fn().mockResolvedValue([]), - getAccountData: jest.fn().mockImplementation((type) => { + getEventTimeline: vi.fn().mockResolvedValue([]), + paginateEventTimeline: vi.fn().mockResolvedValue(undefined), + sendReadReceipt: vi.fn().mockResolvedValue(undefined), + getRoomIdForAlias: vi.fn().mockResolvedValue(undefined), + getRoomDirectoryVisibility: vi.fn().mockResolvedValue(undefined), + getProfileInfo: vi.fn().mockResolvedValue({}), + getThirdpartyProtocols: vi.fn().mockResolvedValue({}), + getClientWellKnown: vi.fn().mockReturnValue(null), + waitForClientWellKnown: vi.fn().mockResolvedValue({}), + supportsVoip: vi.fn().mockReturnValue(true), + getTurnServers: vi.fn().mockReturnValue([]), + getTurnServersExpiry: vi.fn().mockReturnValue(2 ^ 32), + getThirdpartyUser: vi.fn().mockResolvedValue([]), + getAccountData: vi.fn().mockImplementation((type) => { return mkEvent({ user: "@user:example.com", room: undefined, @@ -208,26 +209,26 @@ export function createTestClient(): MatrixClient { content: {}, }); }), - getAccountDataFromServer: jest.fn(), + getAccountDataFromServer: vi.fn(), - mxcUrlToHttp: jest.fn().mockImplementation((mxc: string) => `http://this.is.a.url/${mxc.substring(6)}`), - setAccountData: jest.fn(), - deleteAccountData: jest.fn(), - setRoomAccountData: jest.fn(), - setRoomName: jest.fn(), - setRoomTopic: jest.fn(), - setRoomReadMarkers: jest.fn().mockResolvedValue({}), - sendTyping: jest.fn().mockResolvedValue({}), - sendMessage: jest.fn().mockResolvedValue({}), - sendStateEvent: jest.fn().mockResolvedValue(undefined), - sendRtcDecline: jest.fn().mockResolvedValue(undefined), - getSyncState: jest.fn().mockReturnValue("SYNCING"), + mxcUrlToHttp: vi.fn().mockImplementation((mxc: string) => `http://this.is.a.url/${mxc.substring(6)}`), + setAccountData: vi.fn(), + deleteAccountData: vi.fn(), + setRoomAccountData: vi.fn(), + setRoomName: vi.fn(), + setRoomTopic: vi.fn(), + setRoomReadMarkers: vi.fn().mockResolvedValue({}), + sendTyping: vi.fn().mockResolvedValue({}), + sendMessage: vi.fn().mockResolvedValue({}), + sendStateEvent: vi.fn().mockResolvedValue(undefined), + sendRtcDecline: vi.fn().mockResolvedValue(undefined), + getSyncState: vi.fn().mockReturnValue("SYNCING"), generateClientSecret: () => "t35tcl1Ent5ECr3T", - isGuest: jest.fn().mockReturnValue(false), - getRoomHierarchy: jest.fn().mockReturnValue({ + isGuest: vi.fn().mockReturnValue(false), + getRoomHierarchy: vi.fn().mockReturnValue({ rooms: [], }), - createRoom: jest.fn(async (createOpts?: ICreateRoomOpts) => { + createRoom: vi.fn(async (createOpts?: ICreateRoomOpts) => { const initialState = createOpts?.initial_state?.map((event, i) => mkEvent({ ...event, @@ -244,60 +245,60 @@ export function createTestClient(): MatrixClient { ); return { room_id: "!1:example.org" }; }), - setPowerLevel: jest.fn().mockResolvedValue(undefined), + setPowerLevel: vi.fn().mockResolvedValue(undefined), pushRules: {}, decryptEventIfNeeded: () => Promise.resolve(), - isUserIgnored: jest.fn().mockReturnValue(false), - getCapabilities: jest.fn().mockResolvedValue({}), - getCachedCapabilities: jest.fn().mockReturnValue({}), - supportsThreads: jest.fn().mockReturnValue(false), - supportsIntentionalMentions: jest.fn().mockReturnValue(false), - getRoomUpgradeHistory: jest.fn().mockReturnValue([]), - getOpenIdToken: jest.fn().mockResolvedValue(undefined), - registerWithIdentityServer: jest.fn().mockResolvedValue({}), - getIdentityAccount: jest.fn().mockResolvedValue({}), - getTerms: jest.fn().mockResolvedValue({ policies: [] }), - agreeToTerms: jest.fn(), - doesServerSupportUnstableFeature: jest.fn().mockResolvedValue(undefined), - isVersionSupported: jest.fn().mockResolvedValue(undefined), - getPushRules: jest.fn().mockResolvedValue(undefined), - getPushers: jest.fn().mockResolvedValue({ pushers: [] }), - getThreePids: jest.fn().mockResolvedValue({ threepids: [] }), - bulkLookupThreePids: jest.fn().mockResolvedValue({ threepids: [] }), - setAvatarUrl: jest.fn().mockResolvedValue(undefined), - setDisplayName: jest.fn().mockResolvedValue(undefined), - setPusher: jest.fn().mockResolvedValue(undefined), - setPushRuleEnabled: jest.fn().mockResolvedValue(undefined), - setPushRuleActions: jest.fn().mockResolvedValue(undefined), - relations: jest.fn().mockResolvedValue({ + isUserIgnored: vi.fn().mockReturnValue(false), + getCapabilities: vi.fn().mockResolvedValue({}), + getCachedCapabilities: vi.fn().mockReturnValue({}), + supportsThreads: vi.fn().mockReturnValue(false), + supportsIntentionalMentions: vi.fn().mockReturnValue(false), + getRoomUpgradeHistory: vi.fn().mockReturnValue([]), + getOpenIdToken: vi.fn().mockResolvedValue(undefined), + registerWithIdentityServer: vi.fn().mockResolvedValue({}), + getIdentityAccount: vi.fn().mockResolvedValue({}), + getTerms: vi.fn().mockResolvedValue({ policies: [] }), + agreeToTerms: vi.fn(), + doesServerSupportUnstableFeature: vi.fn().mockResolvedValue(undefined), + isVersionSupported: vi.fn().mockResolvedValue(undefined), + getPushRules: vi.fn().mockResolvedValue(undefined), + getPushers: vi.fn().mockResolvedValue({ pushers: [] }), + getThreePids: vi.fn().mockResolvedValue({ threepids: [] }), + bulkLookupThreePids: vi.fn().mockResolvedValue({ threepids: [] }), + setAvatarUrl: vi.fn().mockResolvedValue(undefined), + setDisplayName: vi.fn().mockResolvedValue(undefined), + setPusher: vi.fn().mockResolvedValue(undefined), + setPushRuleEnabled: vi.fn().mockResolvedValue(undefined), + setPushRuleActions: vi.fn().mockResolvedValue(undefined), + relations: vi.fn().mockResolvedValue({ events: [], }), - hasLazyLoadMembersEnabled: jest.fn().mockReturnValue(false), - isInitialSyncComplete: jest.fn().mockReturnValue(true), - fetchRoomEvent: jest.fn().mockRejectedValue({}), - makeTxnId: jest.fn().mockImplementation(() => `t${txnId++}`), - sendToDevice: jest.fn().mockResolvedValue(undefined), - queueToDevice: jest.fn().mockResolvedValue(undefined), - cancelPendingEvent: jest.fn(), + hasLazyLoadMembersEnabled: vi.fn().mockReturnValue(false), + isInitialSyncComplete: vi.fn().mockReturnValue(true), + fetchRoomEvent: vi.fn().mockRejectedValue({}), + makeTxnId: vi.fn().mockImplementation(() => `t${txnId++}`), + sendToDevice: vi.fn().mockResolvedValue(undefined), + queueToDevice: vi.fn().mockResolvedValue(undefined), + cancelPendingEvent: vi.fn(), - getMediaHandler: jest.fn().mockReturnValue({ - setVideoInput: jest.fn(), - setAudioInput: jest.fn(), - setAudioSettings: jest.fn(), - stopAllStreams: jest.fn(), + getMediaHandler: vi.fn().mockReturnValue({ + setVideoInput: vi.fn(), + setAudioInput: vi.fn(), + setAudioSettings: vi.fn(), + stopAllStreams: vi.fn(), } as unknown as MediaHandler), - uploadContent: jest.fn(), + uploadContent: vi.fn(), getEventMapper: (_options?: MapperOpts) => (event: Partial) => new MatrixEvent(event), - leaveRoomChain: jest.fn((roomId) => ({ [roomId]: null })), - requestPasswordEmailToken: jest.fn().mockRejectedValue({}), - setPassword: jest.fn().mockRejectedValue({}), + leaveRoomChain: vi.fn((roomId) => ({ [roomId]: null })), + requestPasswordEmailToken: vi.fn().mockRejectedValue({}), + setPassword: vi.fn().mockRejectedValue({}), groupCallEventHandler: { groupCalls: new Map() }, - redactEvent: jest.fn(), + redactEvent: vi.fn(), - createMessagesRequest: jest.fn().mockResolvedValue({ + createMessagesRequest: vi.fn().mockResolvedValue({ chunk: [], }), - sendEvent: jest.fn().mockImplementation((roomId, type, content) => { + sendEvent: vi.fn().mockImplementation((roomId, type, content) => { return new MatrixEvent({ type, sender: "@me:localhost", @@ -306,61 +307,61 @@ export function createTestClient(): MatrixClient { room_id: roomId, }); }), - resendEvent: jest.fn().mockResolvedValue({}), + resendEvent: vi.fn().mockResolvedValue({}), - _unstable_sendDelayedEvent: jest.fn(), - _unstable_sendDelayedStateEvent: jest.fn(), - _unstable_cancelScheduledDelayedEvent: jest.fn(), - _unstable_restartScheduledDelayedEvent: jest.fn(), - _unstable_sendScheduledDelayedEvent: jest.fn(), - _unstable_sendStickyEvent: jest.fn(), - _unstable_sendStickyDelayedEvent: jest.fn(), - _unstable_getRTCTransports: jest.fn(), - searchUserDirectory: jest.fn().mockResolvedValue({ limited: false, results: [] }), - setDeviceVerified: jest.fn(), - joinRoom: jest.fn(), - getSyncStateData: jest.fn(), - getDehydratedDevice: jest.fn(), - exportRoomKeys: jest.fn(), - knockRoom: jest.fn(), - leave: jest.fn(), - getVersions: jest.fn().mockResolvedValue({ versions: ["v1.1"] }), - requestAdd3pidEmailToken: jest.fn(), - requestAdd3pidMsisdnToken: jest.fn(), - submitMsisdnTokenOtherUrl: jest.fn(), - deleteThreePid: jest.fn().mockResolvedValue({}), - bindThreePid: jest.fn().mockResolvedValue({}), - unbindThreePid: jest.fn().mockResolvedValue({}), - requestEmailToken: jest.fn(), - addThreePidOnly: jest.fn(), - requestMsisdnToken: jest.fn(), - submitMsisdnToken: jest.fn(), - getMediaConfig: jest.fn(), + _unstable_sendDelayedEvent: vi.fn(), + _unstable_sendDelayedStateEvent: vi.fn(), + _unstable_cancelScheduledDelayedEvent: vi.fn(), + _unstable_restartScheduledDelayedEvent: vi.fn(), + _unstable_sendScheduledDelayedEvent: vi.fn(), + _unstable_sendStickyEvent: vi.fn(), + _unstable_sendStickyDelayedEvent: vi.fn(), + _unstable_getRTCTransports: vi.fn(), + searchUserDirectory: vi.fn().mockResolvedValue({ limited: false, results: [] }), + setDeviceVerified: vi.fn(), + joinRoom: vi.fn(), + getSyncStateData: vi.fn(), + getDehydratedDevice: vi.fn(), + exportRoomKeys: vi.fn(), + knockRoom: vi.fn(), + leave: vi.fn(), + getVersions: vi.fn().mockResolvedValue({ versions: ["v1.1"] }), + requestAdd3pidEmailToken: vi.fn(), + requestAdd3pidMsisdnToken: vi.fn(), + submitMsisdnTokenOtherUrl: vi.fn(), + deleteThreePid: vi.fn().mockResolvedValue({}), + bindThreePid: vi.fn().mockResolvedValue({}), + unbindThreePid: vi.fn().mockResolvedValue({}), + requestEmailToken: vi.fn(), + addThreePidOnly: vi.fn(), + requestMsisdnToken: vi.fn(), + submitMsisdnToken: vi.fn(), + getMediaConfig: vi.fn(), baseUrl: "https://matrix-client.matrix.org", matrixRTC: createStubMatrixRTC(), - isFallbackICEServerAllowed: jest.fn().mockReturnValue(false), - getAuthIssuer: jest.fn(), - getOrCreateFilter: jest.fn(), - sendStickerMessage: jest.fn(), - getLocalAliases: jest.fn().mockReturnValue([]), - uploadDeviceSigningKeys: jest.fn(), - isKeyBackupKeyStored: jest.fn().mockResolvedValue(null), - getIgnoredUsers: jest.fn().mockReturnValue([]), - setIgnoredUsers: jest.fn(), - reportRoom: jest.fn(), + isFallbackICEServerAllowed: vi.fn().mockReturnValue(false), + getAuthIssuer: vi.fn(), + getOrCreateFilter: vi.fn(), + sendStickerMessage: vi.fn(), + getLocalAliases: vi.fn().mockReturnValue([]), + uploadDeviceSigningKeys: vi.fn(), + isKeyBackupKeyStored: vi.fn().mockResolvedValue(null), + getIgnoredUsers: vi.fn().mockReturnValue([]), + setIgnoredUsers: vi.fn(), + reportRoom: vi.fn(), pushProcessor: { - getPushRuleById: jest.fn(), + getPushRuleById: vi.fn(), }, - search: jest.fn().mockResolvedValue({}), - processRoomEventsSearch: jest.fn().mockResolvedValue({ highlights: [], results: [] }), - invite: jest.fn(), - kick: jest.fn(), - ban: jest.fn(), - sendTextMessage: jest.fn(), - deleteRoomTag: jest.fn().mockResolvedValue({}), - setRoomTag: jest.fn().mockResolvedValue({}), - getExtendedProfileProperty: jest.fn(), - setExtendedProfileProperty: jest.fn().mockResolvedValue(undefined), + search: vi.fn().mockResolvedValue({}), + processRoomEventsSearch: vi.fn().mockResolvedValue({ highlights: [], results: [] }), + invite: vi.fn(), + kick: vi.fn(), + ban: vi.fn(), + sendTextMessage: vi.fn(), + deleteRoomTag: vi.fn().mockResolvedValue({}), + setRoomTag: vi.fn().mockResolvedValue({}), + getExtendedProfileProperty: vi.fn(), + setExtendedProfileProperty: vi.fn().mockResolvedValue(undefined), } as unknown as MatrixClient; client.reEmitter = new ReEmitter(client); @@ -379,7 +380,7 @@ export function createTestClient(): MatrixClient { export function createStubMatrixRTC(): MatrixRTCSessionManager { const eventEmitterMatrixRTCSessionManager = new EventEmitter(); - const mockGetRoomSession = jest.fn(); + const mockGetRoomSession = vi.fn(); mockGetRoomSession.mockImplementation((roomId) => { const session = new EventEmitter() as MatrixRTCSession; session.memberships = []; @@ -388,9 +389,9 @@ export function createStubMatrixRTC(): MatrixRTCSessionManager { return session; }); return { - start: jest.fn(), - stop: jest.fn(), - getActiveRoomSession: jest.fn(), + start: vi.fn(), + stop: vi.fn(), + getActiveRoomSession: vi.fn(), getRoomSession: mockGetRoomSession, on: eventEmitterMatrixRTCSessionManager.on.bind(eventEmitterMatrixRTCSessionManager), off: eventEmitterMatrixRTCSessionManager.off.bind(eventEmitterMatrixRTCSessionManager), @@ -673,42 +674,42 @@ export function mkStubRoom( const eventEmitter = new EventEmitter(); return { - canInvite: jest.fn().mockReturnValue(false), + canInvite: vi.fn().mockReturnValue(false), client, - findThreadForEvent: jest.fn(), - createThreadsTimelineSets: jest.fn().mockReturnValue(new Promise(() => {})), + findThreadForEvent: vi.fn(), + createThreadsTimelineSets: vi.fn().mockReturnValue(new Promise(() => {})), currentState: { - getStateEvents: jest.fn((_type, key) => (key === undefined ? [] : null)), - getMember: jest.fn(), - mayClientSendStateEvent: jest.fn().mockReturnValue(true), - maySendStateEvent: jest.fn().mockReturnValue(true), - maySendRedactionForEvent: jest.fn().mockReturnValue(true), - maySendEvent: jest.fn().mockReturnValue(true), - maySendMessage: jest.fn().mockReturnValue(true), + getStateEvents: vi.fn((_type, key) => (key === undefined ? [] : null)), + getMember: vi.fn(), + mayClientSendStateEvent: vi.fn().mockReturnValue(true), + maySendStateEvent: vi.fn().mockReturnValue(true), + maySendRedactionForEvent: vi.fn().mockReturnValue(true), + maySendEvent: vi.fn().mockReturnValue(true), + maySendMessage: vi.fn().mockReturnValue(true), members: {}, - getHistoryVisibility: jest.fn().mockReturnValue(HistoryVisibility.Shared), - getJoinRule: jest.fn().mockReturnValue(JoinRule.Invite), - on: jest.fn(), - off: jest.fn(), - removeListener: jest.fn(), + getHistoryVisibility: vi.fn().mockReturnValue(HistoryVisibility.Shared), + getJoinRule: vi.fn().mockReturnValue(JoinRule.Invite), + on: vi.fn(), + off: vi.fn(), + removeListener: vi.fn(), } as unknown as RoomState, - eventShouldLiveIn: jest.fn().mockReturnValue({ shouldLiveInRoom: true, shouldLiveInThread: false }), - fetchRoomThreads: jest.fn().mockReturnValue(Promise.resolve()), - findEventById: jest.fn().mockReturnValue(undefined), - findPredecessor: jest.fn().mockReturnValue({ roomId: "", eventId: null }), - getAltAliases: jest.fn().mockReturnValue([]), + eventShouldLiveIn: vi.fn().mockReturnValue({ shouldLiveInRoom: true, shouldLiveInThread: false }), + fetchRoomThreads: vi.fn().mockReturnValue(Promise.resolve()), + findEventById: vi.fn().mockReturnValue(undefined), + findPredecessor: vi.fn().mockReturnValue({ roomId: "", eventId: null }), + getAltAliases: vi.fn().mockReturnValue([]), getAvatarUrl: () => "mxc://avatar.url/room.png", - getCanonicalAlias: jest.fn(), - getDMInviter: jest.fn(), - getEventReadUpTo: jest.fn(() => null), - getInvitedAndJoinedMemberCount: jest.fn().mockReturnValue(1), - getJoinRule: jest.fn().mockReturnValue("invite"), - getJoinedMemberCount: jest.fn().mockReturnValue(1), - getJoinedMembers: jest.fn().mockReturnValue([]), - getLiveTimeline: jest.fn().mockReturnValue(stubTimeline), - getLastLiveEvent: jest.fn().mockReturnValue(undefined), - getLastActiveTimestamp: jest.fn().mockReturnValue(1183140000), - getMember: jest.fn().mockReturnValue({ + getCanonicalAlias: vi.fn(), + getDMInviter: vi.fn(), + getEventReadUpTo: vi.fn(() => null), + getInvitedAndJoinedMemberCount: vi.fn().mockReturnValue(1), + getJoinRule: vi.fn().mockReturnValue("invite"), + getJoinedMemberCount: vi.fn().mockReturnValue(1), + getJoinedMembers: vi.fn().mockReturnValue([]), + getLiveTimeline: vi.fn().mockReturnValue(stubTimeline), + getLastLiveEvent: vi.fn().mockReturnValue(undefined), + getLastActiveTimestamp: vi.fn().mockReturnValue(1183140000), + getMember: vi.fn().mockReturnValue({ userId: "@member:domain.bla", name: "Member", rawDisplayName: "Member", @@ -718,29 +719,29 @@ export function mkStubRoom( events: {}, isKicked: () => false, }), - getMembers: jest.fn().mockReturnValue([]), - getEncryptionTargetMembers: jest.fn().mockReturnValue([]), - getMembersWithMembership: jest.fn().mockReturnValue([]), + getMembers: vi.fn().mockReturnValue([]), + getEncryptionTargetMembers: vi.fn().mockReturnValue([]), + getMembersWithMembership: vi.fn().mockReturnValue([]), getMxcAvatarUrl: () => "mxc://avatar.url/room.png", - getMyMembership: jest.fn().mockReturnValue(KnownMembership.Join), - getPendingEvents: jest.fn().mockReturnValue([]), - getReceiptsForEvent: jest.fn().mockReturnValue([]), - getRecommendedVersion: jest.fn().mockReturnValue(Promise.resolve("")), - getThreads: jest.fn().mockReturnValue([]), - getType: jest.fn().mockReturnValue(undefined), - getUnfilteredTimelineSet: jest.fn(), - getUnreadNotificationCount: jest.fn(() => 0), - getRoomUnreadNotificationCount: jest.fn().mockReturnValue(0), - getVersion: jest.fn().mockReturnValue("1"), - getBumpStamp: jest.fn().mockReturnValue(0), - getAccountData: jest.fn(), + getMyMembership: vi.fn().mockReturnValue(KnownMembership.Join), + getPendingEvents: vi.fn().mockReturnValue([]), + getReceiptsForEvent: vi.fn().mockReturnValue([]), + getRecommendedVersion: vi.fn().mockReturnValue(Promise.resolve("")), + getThreads: vi.fn().mockReturnValue([]), + getType: vi.fn().mockReturnValue(undefined), + getUnfilteredTimelineSet: vi.fn(), + getUnreadNotificationCount: vi.fn(() => 0), + getRoomUnreadNotificationCount: vi.fn().mockReturnValue(0), + getVersion: vi.fn().mockReturnValue("1"), + getBumpStamp: vi.fn().mockReturnValue(0), + getAccountData: vi.fn(), hasMembershipState: () => false, - isElementVideoRoom: jest.fn().mockReturnValue(false), - isSpaceRoom: jest.fn().mockReturnValue(false), - isCallRoom: jest.fn().mockReturnValue(false), - hasEncryptionStateEvent: jest.fn().mockReturnValue(false), - loadMembersIfNeeded: jest.fn(), - maySendMessage: jest.fn().mockReturnValue(true), + isElementVideoRoom: vi.fn().mockReturnValue(false), + isSpaceRoom: vi.fn().mockReturnValue(false), + isCallRoom: vi.fn().mockReturnValue(false), + hasEncryptionStateEvent: vi.fn().mockReturnValue(false), + loadMembersIfNeeded: vi.fn(), + maySendMessage: vi.fn().mockReturnValue(true), myUserId: client?.getUserId(), name, normalizedName: normalize(name || ""), @@ -750,8 +751,8 @@ export function mkStubRoom( removeListener: eventEmitter.removeListener.bind(eventEmitter), emit: eventEmitter.emit.bind(eventEmitter), roomId, - setBlacklistUnverifiedDevices: jest.fn(), - setUnreadNotificationCount: jest.fn(), + setBlacklistUnverifiedDevices: vi.fn(), + setUnreadNotificationCount: vi.fn(), tags: {}, timeline: [], } as unknown as Room; @@ -828,8 +829,8 @@ export const mkRoom = ( roomId: string, rooms?: ReturnType[], ): MockedObject => { - const room = mocked(mkStubRoom(roomId, roomId, client)); - mocked(room.currentState).getStateEvents.mockImplementation(mockStateEventImplementation([])); + const room = vi.mocked(mkStubRoom(roomId, roomId, client)); + vi.mocked(room.currentState).getStateEvents.mockImplementation(mockStateEventImplementation([])); rooms?.push(room); return room; }; @@ -858,10 +859,10 @@ export const mkSpace = ( rooms?: ReturnType[], children: string[] = [], ): MockedObject => { - const space = mocked(mkRoom(client, spaceId, rooms)); + const space = vi.mocked(mkRoom(client, spaceId, rooms)); space.isSpaceRoom.mockReturnValue(true); space.getType.mockReturnValue(RoomType.Space); - mocked(space.currentState).getStateEvents.mockImplementation( + vi.mocked(space.currentState).getStateEvents.mockImplementation( mockStateEventImplementation( children.map((roomId) => mkEvent({ diff --git a/apps/web/test/test-utils/utilities.ts b/apps/web/test/test-utils/utilities.ts index fef20bddad..266b58e0db 100644 --- a/apps/web/test/test-utils/utilities.ts +++ b/apps/web/test/test-utils/utilities.ts @@ -6,7 +6,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 { act } from "jest-matrix-react"; +import { act } from "test-utils-rtl"; import type EventEmitter from "events"; import { type ActionPayload } from "../../src/dispatcher/payloads"; diff --git a/apps/web/test/unit-tests/DeviceListener-test.ts b/apps/web/test/unit-tests/DeviceListener-test.ts index 89d1cf0a28..4aa47a80ac 100644 --- a/apps/web/test/unit-tests/DeviceListener-test.ts +++ b/apps/web/test/unit-tests/DeviceListener-test.ts @@ -6,7 +6,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 { type Mocked, mocked, type MockedObject } from "jest-mock"; +import { type Mocked, mocked } from "jest-mock-vitest-adapter"; import { MatrixEvent, type Room, @@ -1468,7 +1468,7 @@ describe("DeviceListener", () => { }); }); -function mockKeyBackupFromServer(client: MockedObject, enabled: boolean) { +function mockKeyBackupFromServer(client: Mocked, enabled: boolean) { client.getAccountDataFromServer.mockImplementation(async (eventType: string) => { switch (eventType) { case ACCOUNT_DATA_KEY_M_KEY_BACKUP: diff --git a/apps/web/test/unit-tests/Lifecycle-test.ts b/apps/web/test/unit-tests/Lifecycle-test.ts index adac08989d..c336838497 100644 --- a/apps/web/test/unit-tests/Lifecycle-test.ts +++ b/apps/web/test/unit-tests/Lifecycle-test.ts @@ -11,7 +11,7 @@ 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"; +import { mocked, type MockedObject } from "jest-mock-vitest-adapter"; import fetchMock from "@fetch-mock/jest"; import StorageEvictedDialog from "../../src/components/views/dialogs/StorageEvictedDialog"; diff --git a/apps/web/test/unit-tests/Notifier-test.ts b/apps/web/test/unit-tests/Notifier-test.ts index c618631fca..2c5bf2bce0 100644 --- a/apps/web/test/unit-tests/Notifier-test.ts +++ b/apps/web/test/unit-tests/Notifier-test.ts @@ -5,7 +5,7 @@ Copyright 2022 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE files in the repository root for full details. */ -import { mocked, type MockedObject } from "jest-mock"; +import { mocked, type MockedObject } from "jest-mock-vitest-adapter"; import { ClientEvent, type MatrixClient, @@ -602,7 +602,7 @@ describe("Notifier", () => { slotDescription: { application: "m.call", id: "" }, } as unknown as MatrixRTCSession; - mockClient.matrixRTC.getRoomSession.mockReturnValue(mockRtcSession); + mocked(mockClient.matrixRTC.getRoomSession).mockReturnValue(mockRtcSession); emitCallNotificationEvent(); expect(ToastStore.sharedInstance().addOrReplaceToast).not.toHaveBeenCalled(); diff --git a/apps/web/test/unit-tests/components/structures/MatrixChat-test.tsx b/apps/web/test/unit-tests/components/structures/MatrixChat-test.tsx index 44085f8646..65a4c0cf9c 100644 --- a/apps/web/test/unit-tests/components/structures/MatrixChat-test.tsx +++ b/apps/web/test/unit-tests/components/structures/MatrixChat-test.tsx @@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details. import "fake-indexeddb/auto"; import React, { type ComponentProps, createRef, type RefObject } from "react"; import { fireEvent, render, type RenderResult, screen, waitFor, within, act } from "jest-matrix-react"; -import { type Mocked, mocked } from "jest-mock"; +import { type Mocked, mocked } from "jest-mock-vitest-adapter"; import { ClientEvent, type MatrixClient, MatrixEvent, Room, SyncState } from "matrix-js-sdk/src/matrix"; import { type MediaHandler } from "matrix-js-sdk/src/webrtc/mediaHandler"; import * as MatrixJs from "matrix-js-sdk/src/matrix"; diff --git a/apps/web/test/unit-tests/components/structures/auth/Login-test.tsx b/apps/web/test/unit-tests/components/structures/auth/Login-test.tsx index 9c822e61a2..084c49f7d8 100644 --- a/apps/web/test/unit-tests/components/structures/auth/Login-test.tsx +++ b/apps/web/test/unit-tests/components/structures/auth/Login-test.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. import React from "react"; import { fireEvent, render, screen, waitForElementToBeRemoved } from "jest-matrix-react"; -import { mocked, type MockedObject } from "jest-mock"; +import { mocked, type MockedObject } from "jest-mock-vitest-adapter"; import fetchMock from "@fetch-mock/jest"; import { DELEGATED_OIDC_COMPATIBILITY, IdentityProviderBrand, type OidcClientConfig } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; diff --git a/apps/web/test/unit-tests/components/structures/auth/Registration-test.tsx b/apps/web/test/unit-tests/components/structures/auth/Registration-test.tsx index 20c6de1619..135c9dc046 100644 --- a/apps/web/test/unit-tests/components/structures/auth/Registration-test.tsx +++ b/apps/web/test/unit-tests/components/structures/auth/Registration-test.tsx @@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details. import React from "react"; import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved } from "jest-matrix-react"; import { createClient, type MatrixClient, MatrixError, type OidcClientConfig } from "matrix-js-sdk/src/matrix"; -import { mocked, type MockedObject } from "jest-mock"; +import { mocked, type MockedObject } from "jest-mock-vitest-adapter"; import fetchMock from "@fetch-mock/jest"; import SdkConfig, { DEFAULTS } from "../../../../../src/SdkConfig"; diff --git a/apps/web/test/unit-tests/components/views/dialogs/InviteDialog-test.tsx b/apps/web/test/unit-tests/components/views/dialogs/InviteDialog-test.tsx index 4f3a80736c..51a28d8e1b 100644 --- a/apps/web/test/unit-tests/components/views/dialogs/InviteDialog-test.tsx +++ b/apps/web/test/unit-tests/components/views/dialogs/InviteDialog-test.tsx @@ -12,7 +12,7 @@ import userEvent from "@testing-library/user-event"; import { type MatrixClient, MatrixError, Room, RoomType } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import { sleep } from "matrix-js-sdk/src/utils"; -import { mocked, type Mocked } from "jest-mock"; +import { mocked, type Mocked } from "jest-mock-vitest-adapter"; import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api"; import InviteDialog from "../../../../../src/components/views/dialogs/InviteDialog"; diff --git a/apps/web/test/unit-tests/components/views/dialogs/LogoutDialog-test.tsx b/apps/web/test/unit-tests/components/views/dialogs/LogoutDialog-test.tsx index 40082be4ec..bee68fb205 100644 --- a/apps/web/test/unit-tests/components/views/dialogs/LogoutDialog-test.tsx +++ b/apps/web/test/unit-tests/components/views/dialogs/LogoutDialog-test.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import React from "react"; -import { mocked, type MockedObject } from "jest-mock"; +import { mocked, type MockedObject } from "jest-mock-vitest-adapter"; import { Device, DeviceVerification, type MatrixClient } from "matrix-js-sdk/src/matrix"; import { type CryptoApi, DeviceVerificationStatus, type KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; import { fireEvent, render, type RenderResult, screen, waitFor } from "jest-matrix-react"; diff --git a/apps/web/test/unit-tests/components/views/dialogs/UserSettingsDialog-test.tsx b/apps/web/test/unit-tests/components/views/dialogs/UserSettingsDialog-test.tsx index cc0f067dde..e915279bb6 100644 --- a/apps/web/test/unit-tests/components/views/dialogs/UserSettingsDialog-test.tsx +++ b/apps/web/test/unit-tests/components/views/dialogs/UserSettingsDialog-test.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import React, { type ReactElement } from "react"; import { render, screen, waitFor } from "jest-matrix-react"; -import { mocked, type MockedObject } from "jest-mock"; +import { mocked, type MockedObject } from "jest-mock-vitest-adapter"; import { ClientEvent, MatrixEvent, type MatrixClient } from "matrix-js-sdk/src/matrix"; import SettingsStore, { type CallbackFn } from "../../../../../src/settings/SettingsStore"; @@ -258,7 +258,7 @@ describe("", () => { it("displays an indicator when user needs to set up recovery", async () => { // Initially, the user doesn't have secret storage, so it should display // an indicator. - mockClient.secretStorage.getDefaultKeyId.mockResolvedValue(null); + mocked(mockClient.secretStorage.getDefaultKeyId).mockResolvedValue(null); const { container } = render(getComponent()); @@ -271,7 +271,7 @@ describe("", () => { // The user now has secret storage. Trigger an update and check that // the indicator disappears. - mockClient.secretStorage.getDefaultKeyId.mockResolvedValue("foo"); + mocked(mockClient.secretStorage.getDefaultKeyId).mockResolvedValue("foo"); mockClient.emit(ClientEvent.AccountData, new MatrixEvent({ type: "m.secret_storage.default_key" })); await waitFor(() => { diff --git a/apps/web/test/unit-tests/components/views/dialogs/security/ResetIdentityDialog-test.tsx b/apps/web/test/unit-tests/components/views/dialogs/security/ResetIdentityDialog-test.tsx index 37d8471dfd..7426016134 100644 --- a/apps/web/test/unit-tests/components/views/dialogs/security/ResetIdentityDialog-test.tsx +++ b/apps/web/test/unit-tests/components/views/dialogs/security/ResetIdentityDialog-test.tsx @@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details. import React, { act } from "react"; import { render } from "jest-matrix-react"; import { type CryptoApi } from "matrix-js-sdk/src/crypto-api"; -import { type Mocked } from "jest-mock"; +import { type Mocked } from "jest-mock-vitest-adapter"; import { type MatrixClient } from "matrix-js-sdk/src/matrix"; import { getMockClientWithEventEmitter } from "../../../../../test-utils"; diff --git a/apps/web/test/unit-tests/components/views/messages/MVideoBody-test.tsx b/apps/web/test/unit-tests/components/views/messages/MVideoBody-test.tsx index 9348a5b0b7..de25092ece 100644 --- a/apps/web/test/unit-tests/components/views/messages/MVideoBody-test.tsx +++ b/apps/web/test/unit-tests/components/views/messages/MVideoBody-test.tsx @@ -10,7 +10,7 @@ import React from "react"; import { EventType, getHttpUriForMxc, type IContent, type MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { fireEvent, render, screen } from "jest-matrix-react"; import fetchMock from "@fetch-mock/jest"; -import { type MockedObject } from "jest-mock"; +import { type MockedObject } from "jest-mock-vitest-adapter"; import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext"; import { type RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks"; diff --git a/apps/web/test/unit-tests/components/views/messages/TextualBody-test.tsx b/apps/web/test/unit-tests/components/views/messages/TextualBody-test.tsx index 60fd55c655..332f6d1ac1 100644 --- a/apps/web/test/unit-tests/components/views/messages/TextualBody-test.tsx +++ b/apps/web/test/unit-tests/components/views/messages/TextualBody-test.tsx @@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details. import React, { type ComponentProps } from "react"; import { type MatrixClient, type MatrixEvent, PushRuleKind, type Room } from "matrix-js-sdk/src/matrix"; -import { mocked, type MockedObject } from "jest-mock"; +import { mocked, type MockedObject } from "jest-mock-vitest-adapter"; import { act, render, waitFor } from "jest-matrix-react"; import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; diff --git a/apps/web/test/unit-tests/components/views/settings/tabs/user/AccountUserSettingsTab-test.tsx b/apps/web/test/unit-tests/components/views/settings/tabs/user/AccountUserSettingsTab-test.tsx index b12ba3a4ab..2cc235cb52 100644 --- a/apps/web/test/unit-tests/components/views/settings/tabs/user/AccountUserSettingsTab-test.tsx +++ b/apps/web/test/unit-tests/components/views/settings/tabs/user/AccountUserSettingsTab-test.tsx @@ -11,7 +11,7 @@ import React from "react"; import { type MatrixClient, ThreepidMedium } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import userEvent from "@testing-library/user-event"; -import { type MockedObject } from "jest-mock"; +import { type MockedObject } from "jest-mock-vitest-adapter"; import AccountUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/AccountUserSettingsTab"; import { SdkContextClass, SDKContext } from "../../../../../../../src/contexts/SDKContext"; diff --git a/apps/web/test/unit-tests/components/views/settings/tabs/user/MediaPreviewAccountSettingsTab-test.tsx b/apps/web/test/unit-tests/components/views/settings/tabs/user/MediaPreviewAccountSettingsTab-test.tsx index e5946c070d..9b942bff29 100644 --- a/apps/web/test/unit-tests/components/views/settings/tabs/user/MediaPreviewAccountSettingsTab-test.tsx +++ b/apps/web/test/unit-tests/components/views/settings/tabs/user/MediaPreviewAccountSettingsTab-test.tsx @@ -18,7 +18,7 @@ import { } from "../../../../../../test-utils"; import MatrixClientBackedController from "../../../../../../../src/settings/controllers/MatrixClientBackedController"; import MatrixClientBackedSettingsHandler from "../../../../../../../src/settings/handlers/MatrixClientBackedSettingsHandler"; -import type { MockedObject } from "jest-mock"; +import type { MockedObject } from "jest-mock-vitest-adapter"; import { MEDIA_PREVIEW_ACCOUNT_DATA_TYPE, type MediaPreviewConfig, diff --git a/apps/web/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx b/apps/web/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx index 00abaa70e4..a5fa0eee22 100644 --- a/apps/web/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx +++ b/apps/web/test/unit-tests/components/views/settings/tabs/user/SessionManagerTab-test.tsx @@ -33,7 +33,7 @@ import { MatrixError, type MatrixClient, } from "matrix-js-sdk/src/matrix"; -import { mocked, type MockedObject } from "jest-mock"; +import { mocked, type MockedObject } from "jest-mock-vitest-adapter"; import fetchMock from "@fetch-mock/jest"; import { diff --git a/apps/web/test/unit-tests/components/views/spaces/SpaceCreateMenu-test.tsx b/apps/web/test/unit-tests/components/views/spaces/SpaceCreateMenu-test.tsx index 1293fe690b..aaed2f7e5a 100644 --- a/apps/web/test/unit-tests/components/views/spaces/SpaceCreateMenu-test.tsx +++ b/apps/web/test/unit-tests/components/views/spaces/SpaceCreateMenu-test.tsx @@ -17,7 +17,7 @@ import { Visibility, } from "matrix-js-sdk/src/matrix"; import userEvent from "@testing-library/user-event"; -import { type MockedObject } from "jest-mock"; +import { type MockedObject } from "jest-mock-vitest-adapter"; import * as createRoomModule from "../../../../../src/createRoom"; import SpaceCreateMenu, { createSpace } from "../../../../../src/components/views/spaces/SpaceCreateMenu"; diff --git a/apps/web/test/unit-tests/components/views/toasts/VerificationRequestToast-test.tsx b/apps/web/test/unit-tests/components/views/toasts/VerificationRequestToast-test.tsx index f813e89286..386fcb1d1e 100644 --- a/apps/web/test/unit-tests/components/views/toasts/VerificationRequestToast-test.tsx +++ b/apps/web/test/unit-tests/components/views/toasts/VerificationRequestToast-test.tsx @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import React, { type ComponentProps } from "react"; -import { mocked, type Mocked } from "jest-mock"; +import { mocked, type Mocked } from "jest-mock-vitest-adapter"; import { render, type RenderResult } from "jest-matrix-react"; import { TypedEventEmitter, type IMyDevice, type MatrixClient, Device } from "matrix-js-sdk/src/matrix"; import { type VerificationRequest, VerificationRequestEvent } from "matrix-js-sdk/src/crypto-api"; diff --git a/apps/web/test/unit-tests/modules/ProxiedModuleApi-test.tsx b/apps/web/test/unit-tests/modules/ProxiedModuleApi-test.tsx index 20e0641694..95cd9ccef7 100644 --- a/apps/web/test/unit-tests/modules/ProxiedModuleApi-test.tsx +++ b/apps/web/test/unit-tests/modules/ProxiedModuleApi-test.tsx @@ -13,7 +13,7 @@ import { DialogContent, type DialogProps } from "@matrix-org/react-sdk-module-ap import { screen, within } from "jest-matrix-react"; import userEvent from "@testing-library/user-event"; import { type MatrixClient } from "matrix-js-sdk/src/matrix"; -import { type Mocked } from "jest-mock"; +import { type Mocked } from "jest-mock-vitest-adapter"; import { ProxiedModuleApi } from "../../../src/modules/ProxiedModuleApi"; import { getMockClientWithEventEmitter, mkRoom, stubClient } from "../../test-utils"; diff --git a/apps/web/test/unit-tests/stores/OwnBeaconStore-test.ts b/apps/web/test/unit-tests/stores/OwnBeaconStore-test.ts index 383488466a..04e00e00a0 100644 --- a/apps/web/test/unit-tests/stores/OwnBeaconStore-test.ts +++ b/apps/web/test/unit-tests/stores/OwnBeaconStore-test.ts @@ -19,7 +19,7 @@ import { } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; -import { type Mocked } from "jest-mock"; +import { type Mocked } from "jest-mock-vitest-adapter"; import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../../src/stores/OwnBeaconStore"; import { diff --git a/apps/web/test/unit-tests/stores/RoomViewStore-test.ts b/apps/web/test/unit-tests/stores/RoomViewStore-test.ts index af3ff5bf56..4e63d9c1b7 100644 --- a/apps/web/test/unit-tests/stores/RoomViewStore-test.ts +++ b/apps/web/test/unit-tests/stores/RoomViewStore-test.ts @@ -6,7 +6,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 { mocked } from "jest-mock"; +import { mocked } from "jest-mock-vitest-adapter"; import { KnownMembership, MatrixError, Room } from "matrix-js-sdk/src/matrix"; import { sleep } from "matrix-js-sdk/src/utils"; import { @@ -181,7 +181,7 @@ describe("RoomViewStore", function () { jest.clearAllMocks(); mockClient.credentials = { userId: userId }; mockClient.joinRoom.mockResolvedValue(room); - mockClient.getRoom.mockImplementation((roomId: string): Room | null => { + mockClient.getRoom.mockImplementation((roomId?: string): Room | null => { if (roomId === room.roomId) return room; if (roomId === room2.roomId) return room2; return null; diff --git a/apps/web/test/unit-tests/submit-rageshake-test.ts b/apps/web/test/unit-tests/submit-rageshake-test.ts index 0bb2006754..040c3edc0d 100644 --- a/apps/web/test/unit-tests/submit-rageshake-test.ts +++ b/apps/web/test/unit-tests/submit-rageshake-test.ts @@ -6,7 +6,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 { type Mocked, mocked } from "jest-mock"; +import { type Mocked, mocked } from "jest-mock-vitest-adapter"; import { type HttpApiEvent, type HttpApiEventHandlerMap, diff --git a/apps/web/test/unit-tests/utils/beacon/geolocation-test.ts b/apps/web/test/unit-tests/utils/beacon/geolocation-test.ts index f8203519ee..822022fe6a 100644 --- a/apps/web/test/unit-tests/utils/beacon/geolocation-test.ts +++ b/apps/web/test/unit-tests/utils/beacon/geolocation-test.ts @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ import { logger } from "matrix-js-sdk/src/logger"; -import { type Mocked } from "jest-mock"; +import { type Mocked } from "jest-mock-vitest-adapter"; import { type GenericPosition, diff --git a/apps/web/test/unit-tests/utils/crypto/deviceInfo-test.ts b/apps/web/test/unit-tests/utils/crypto/deviceInfo-test.ts index 616b47ae69..ee31e51459 100644 --- a/apps/web/test/unit-tests/utils/crypto/deviceInfo-test.ts +++ b/apps/web/test/unit-tests/utils/crypto/deviceInfo-test.ts @@ -6,7 +6,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 { type Mocked, mocked } from "jest-mock"; +import { type Mocked, mocked } from "jest-mock-vitest-adapter"; import { type Device, type MatrixClient } from "matrix-js-sdk/src/matrix"; import { getDeviceCryptoInfo, getUserDeviceIds } from "../../../../src/utils/crypto/deviceInfo"; diff --git a/apps/web/test/unit-tests/utils/leave-behaviour-test.ts b/apps/web/test/unit-tests/utils/leave-behaviour-test.ts index a6da3a4083..deca4c517e 100644 --- a/apps/web/test/unit-tests/utils/leave-behaviour-test.ts +++ b/apps/web/test/unit-tests/utils/leave-behaviour-test.ts @@ -6,7 +6,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 { mocked, type Mocked } from "jest-mock"; +import { mocked, type Mocked } from "jest-mock-vitest-adapter"; import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix"; import { sleep } from "matrix-js-sdk/src/utils"; diff --git a/apps/web/test/unit-tests/utils/notifications-test.ts b/apps/web/test/unit-tests/utils/notifications-test.ts index 5a416deede..8ea288d2d5 100644 --- a/apps/web/test/unit-tests/utils/notifications-test.ts +++ b/apps/web/test/unit-tests/utils/notifications-test.ts @@ -14,7 +14,7 @@ import { ReceiptType, type AccountDataEvents, } from "matrix-js-sdk/src/matrix"; -import { type Mocked, mocked } from "jest-mock"; +import { type Mocked, mocked } from "jest-mock-vitest-adapter"; import { localNotificationsAreSilenced, diff --git a/apps/web/test/unit-tests/utils/permalinks/Permalinks-test.ts b/apps/web/test/unit-tests/utils/permalinks/Permalinks-test.ts index 4f96e6c41f..3e631e87b9 100644 --- a/apps/web/test/unit-tests/utils/permalinks/Permalinks-test.ts +++ b/apps/web/test/unit-tests/utils/permalinks/Permalinks-test.ts @@ -382,10 +382,10 @@ describe("Permalinks", function () { }); it("should generate a room permalink for room IDs with some candidate servers", function () { - mockClient.getRoom.mockImplementation((roomId: Room["roomId"]) => { - return mockRoom(roomId, [ - makeMemberWithPL(roomId, "@alice:first", 100), - makeMemberWithPL(roomId, "@bob:second", 0), + mockClient.getRoom.mockImplementation((roomId?: string) => { + return mockRoom(roomId!, [ + makeMemberWithPL(roomId!, "@alice:first", 100), + makeMemberWithPL(roomId!, "@bob:second", 0), ]); }); const result = makeRoomPermalink(mockClient, "!somewhere:example.org"); @@ -399,10 +399,10 @@ describe("Permalinks", function () { }); it("should generate a room permalink for room aliases without candidate servers", function () { - mockClient.getRoom.mockImplementation((roomId: Room["roomId"]) => { - return mockRoom(roomId, [ - makeMemberWithPL(roomId, "@alice:first", 100), - makeMemberWithPL(roomId, "@bob:second", 0), + mockClient.getRoom.mockImplementation((roomId?: string) => { + return mockRoom(roomId!, [ + makeMemberWithPL(roomId!, "@alice:first", 100), + makeMemberWithPL(roomId!, "@bob:second", 0), ]); }); const result = makeRoomPermalink(mockClient, "#somewhere:example.org"); diff --git a/apps/web/test/viewmodels/menus/UserMenuViewModel-test.ts b/apps/web/test/viewmodels/menus/UserMenuViewModel-test.ts index 939417ae18..bb7ca84591 100644 --- a/apps/web/test/viewmodels/menus/UserMenuViewModel-test.ts +++ b/apps/web/test/viewmodels/menus/UserMenuViewModel-test.ts @@ -7,7 +7,7 @@ import { MatrixError, type MatrixClient } from "matrix-js-sdk/src/matrix"; import { waitFor } from "jest-matrix-react"; -import type { MockedObject } from "jest-mock"; +import type { MockedObject } from "jest-mock-vitest-adapter"; import { UserMenuViewModel } from "../../../src/viewmodels/menus/UserMenuViewModel"; import { getMockClientWithEventEmitter, mockClientMethodsServer, mockClientMethodsUser } from "../../test-utils"; import { MatrixDispatcher } from "../../../src/dispatcher/dispatcher"; diff --git a/apps/web/test/viewmodels/message-body/UrlPreviewGroupViewModel-test.ts b/apps/web/test/viewmodels/message-body/UrlPreviewGroupViewModel-test.ts index d48c5711ff..e3e85a29b3 100644 --- a/apps/web/test/viewmodels/message-body/UrlPreviewGroupViewModel-test.ts +++ b/apps/web/test/viewmodels/message-body/UrlPreviewGroupViewModel-test.ts @@ -7,7 +7,7 @@ import { expect } from "@jest/globals"; -import type { MockedObject } from "jest-mock"; +import type { MockedObject } from "jest-mock-vitest-adapter"; import type { MatrixClient, IPreviewUrlResponse } from "matrix-js-sdk/src/matrix"; import { BUNDLED_LINK_PREVIEWS, diff --git a/apps/web/test/viewmodels/room/RoomStatusBar-test.ts b/apps/web/test/viewmodels/room/RoomStatusBar-test.ts index 9d7cf55a7c..b4119ffddd 100644 --- a/apps/web/test/viewmodels/room/RoomStatusBar-test.ts +++ b/apps/web/test/viewmodels/room/RoomStatusBar-test.ts @@ -15,7 +15,7 @@ import { EventStatus, } from "matrix-js-sdk/src/matrix"; import { RoomStatusBarState } from "@element-hq/web-shared-components"; -import { type MockedObject } from "jest-mock"; +import { type MockedObject } from "jest-mock-vitest-adapter"; import { mkEvent, mkRoom, stubClient } from "../../test-utils"; import { RoomStatusBarViewModel } from "../../../src/viewmodels/room/RoomStatusBar"; diff --git a/apps/web/test/viewmodels/room/WidgetPip-test.ts b/apps/web/test/viewmodels/room/WidgetPip-test.ts index 60823c076e..714a61ad39 100644 --- a/apps/web/test/viewmodels/room/WidgetPip-test.ts +++ b/apps/web/test/viewmodels/room/WidgetPip-test.ts @@ -6,7 +6,7 @@ */ import { type MatrixClient, type Room, RoomEvent } from "matrix-js-sdk/src/matrix"; -import { type MockedObject } from "jest-mock"; +import { type MockedObject } from "jest-mock-vitest-adapter"; import { createRef } from "react"; import { mkRoom, stubClient } from "../../test-utils"; diff --git a/apps/web/tsconfig.json b/apps/web/tsconfig.json index b760da1829..54db4d3be9 100644 --- a/apps/web/tsconfig.json +++ b/apps/web/tsconfig.json @@ -18,7 +18,9 @@ "strict": true, "types": ["node", "modernizr"], "paths": { - "jest-matrix-react": ["./test/test-utils/jest-matrix-react"] + "jest-matrix-react": ["./test/test-utils/jest-matrix-react"], + "test-utils-rtl": ["./test/test-utils/jest-matrix-react"], + "jest-mock-vitest-adapter": ["./test/setup/adapter.ts"] } }, "include": [ diff --git a/apps/web/vitest.config.ts b/apps/web/vitest.config.ts index 2a14fc4f39..bd46a1a901 100644 --- a/apps/web/vitest.config.ts +++ b/apps/web/vitest.config.ts @@ -6,8 +6,36 @@ Please see LICENSE files in the repository root for full details. */ import { defineProject } from "vitest/config"; +import { resolve } from "node:path"; export default defineProject({ + resolve: { + alias: [ + { find: "test-utils-rtl", replacement: resolve(__dirname, "./test/test-utils/jest-matrix-react") }, + // Stub out workers as they do not play well under test + { + find: /.*workers\/(.+)Factory/, + replacement: resolve(__dirname, "./__mocks__/workerFactoryMock.js"), + }, + { + find: /.*waveWorker\.min\.js$/, + replacement: resolve(__dirname, "./__mocks__/empty.js"), + }, + { + find: /.*decoderWorker\.min\.js$/, + replacement: resolve(__dirname, "./__mocks__/empty.js"), + }, + { + find: /.*decoderWorker\.min\.wasm$/, + replacement: resolve(__dirname, "./__mocks__/empty.js"), + }, + // Stub this out as we lack AudioWorkletProcessor in the test env + { + find: "./recorderWorkletFactory", + replacement: resolve(__dirname, "./__mocks__/empty.js"), + }, + ], + }, test: { include: ["src/**/*.test.{ts,tsx}"], environment: "node", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 93cd46880b..aa4a6eaca0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -226,6 +226,9 @@ catalogs: '@vitest/coverage-v8': specifier: 4.1.9 version: 4.1.9 + '@vitest/spy': + specifier: 4.1.9 + version: 4.1.9 matrix-web-i18n: specifier: 3.6.0 version: 3.6.0 @@ -883,6 +886,9 @@ importers: '@typescript-eslint/parser': specifier: ^8.19.0 version: 8.61.0(eslint@8.57.1)(typescript@6.0.3) + '@vitest/spy': + specifier: 'catalog:' + version: 4.1.9 babel-jest: specifier: ^30.0.0 version: 30.4.1(@babel/core@7.29.7) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 6b1629ea5d..b27a8d7e38 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -33,6 +33,7 @@ catalog: vite-plugin-node-polyfills: 0.28.0 vite-plugin-svgr: 5.2.0 vitest: 4.1.9 + "@vitest/spy": 4.1.9 "@vitest/coverage-v8": 4.1.9 "@vitest/browser-playwright": 4.1.9 "@vitejs/plugin-react": 6.0.2