From 6fda0ad60f33d0bfcfb3c1830a5485801265ef1e Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 7 Jul 2026 10:50:40 +0100 Subject: [PATCH] Migrate more jest tests to vitest (#33922) * Migrate more jest tests to vitest * Fix jest config * Fix jest config * Make remaining jest tests type-happy * Iterate * Fix Notifier import cycle * Fix tests * Delint * Iterate * Handle SDKContextClass `client` initialisation internally Rather than via MatrixChat - this is predominantly for Lifecycle tests as they don't use a MatrixChat and it doesn't make much sense for this component to own this state. * Fix tests * Iterate * Simplify diff * Improve coverage * Improve coverage * Iterate --- .../DateUtils.test.ts} | 30 ++++++---- apps/web/src/test/setupGlobals.ts | 4 ++ apps/web/src/test/setupTests.ts | 4 +- .../utils/ErrorUtils.test.ts} | 7 ++- .../utils/EventUtils.test.ts} | 32 +++++++---- .../utils/FileUtils.test.ts} | 3 +- .../__snapshots__/ErrorUtils.test.ts.snap} | 26 ++++----- .../utils/leave-behaviour.test.ts} | 56 ++++++++++--------- .../room/WidgetPipViewModel.test.ts} | 38 +++++++------ .../web/test/test-utils/jest-matrix-react.tsx | 8 ++- 10 files changed, 120 insertions(+), 88 deletions(-) rename apps/web/{test/unit-tests/utils/DateUtils-test.ts => src/DateUtils.test.ts} (94%) rename apps/web/{test/unit-tests/utils/ErrorUtils-test.ts => src/utils/ErrorUtils.test.ts} (97%) rename apps/web/{test/unit-tests/utils/EventUtils-test.ts => src/utils/EventUtils.test.ts} (94%) rename apps/web/{test/unit-tests/utils/FileUtils-test.ts => src/utils/FileUtils.test.ts} (94%) rename apps/web/{test/unit-tests/utils/__snapshots__/ErrorUtils-test.ts.snap => src/utils/__snapshots__/ErrorUtils.test.ts.snap} (72%) rename apps/web/{test/unit-tests/utils/leave-behaviour-test.ts => src/utils/leave-behaviour.test.ts} (74%) rename apps/web/{test/viewmodels/room/WidgetPip-test.ts => src/viewmodels/room/WidgetPipViewModel.test.ts} (71%) diff --git a/apps/web/test/unit-tests/utils/DateUtils-test.ts b/apps/web/src/DateUtils.test.ts similarity index 94% rename from apps/web/test/unit-tests/utils/DateUtils-test.ts rename to apps/web/src/DateUtils.test.ts index f677b4e044..8cdeaf2857 100644 --- a/apps/web/test/unit-tests/utils/DateUtils-test.ts +++ b/apps/web/src/DateUtils.test.ts @@ -6,6 +6,10 @@ 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, beforeAll, afterAll } from "vitest"; + import { formatSeconds, formatRelativeTime, @@ -25,9 +29,11 @@ import { HOUR_MS, MINUTE_MS, DAY_MS, -} from "../../../src/DateUtils"; -import { REPEATABLE_DATE, mockIntlDateTimeFormat, unmockIntlDateTimeFormat } from "../../test-utils"; -import * as languageSettings from "../../../src/i18n/settings"; +} from "./DateUtils"; +import { REPEATABLE_DATE, mockIntlDateTimeFormat, unmockIntlDateTimeFormat } from "../test/test-utils"; +import * as languageSettings from "./i18n/settings"; + +vi.mock("./TimezoneHandler", () => ({ getUserTimezone: () => "UTC" })); describe("getDaysArray", () => { it("should return Sunday-Saturday in long mode", () => { @@ -166,13 +172,13 @@ describe("getMonthsArray", () => { describe("formatDate", () => { beforeAll(() => { - jest.useFakeTimers(); - jest.setSystemTime(REPEATABLE_DATE); + vi.useFakeTimers(); + vi.setSystemTime(REPEATABLE_DATE); }); afterAll(() => { - jest.setSystemTime(jest.getRealSystemTime()); - jest.useRealTimers(); + vi.setSystemTime(vi.getRealSystemTime()); + vi.useRealTimers(); }); it("should return time string if date is within same day", () => { @@ -255,14 +261,14 @@ describe("formatSeconds", () => { describe("formatRelativeTime", () => { beforeAll(() => { - jest.useFakeTimers(); + vi.useFakeTimers(); // Tuesday, 2 November 2021 11:18:03 UTC - jest.setSystemTime(1635851883000); + vi.setSystemTime(1635851883000); }); afterAll(() => { - jest.setSystemTime(jest.getRealSystemTime()); - jest.useRealTimers(); + vi.setSystemTime(vi.getRealSystemTime()); + vi.useRealTimers(); }); it("returns hour format for events created in the same day", () => { @@ -369,7 +375,7 @@ describe("formatLocalDateShort()", () => { }); const timestamp = new Date("Fri Dec 17 2021 09:09:00 GMT+0100 (Central European Standard Time)").getTime(); it("formats date correctly by locale", () => { - const locale = jest.spyOn(languageSettings, "getUserLanguage"); + const locale = vi.spyOn(languageSettings, "getUserLanguage"); mockIntlDateTimeFormat(); // format is DD/MM/YY diff --git a/apps/web/src/test/setupGlobals.ts b/apps/web/src/test/setupGlobals.ts index 83aa3a0c57..63c8002847 100644 --- a/apps/web/src/test/setupGlobals.ts +++ b/apps/web/src/test/setupGlobals.ts @@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details. import { vi } from "vitest"; import { mocks } from "../../test/setup/mocks.ts"; +import SdkConfig, { DEFAULTS } from "../SdkConfig"; // set up AudioContext API mock vi.stubGlobal("AudioContext", function () { @@ -28,3 +29,6 @@ if (globalThis.window === undefined) { setTimeout: globalThis.setTimeout, }); } + +// uninitialised SdkConfig causes lots of warnings in console, init with defaults +SdkConfig.put(DEFAULTS); diff --git a/apps/web/src/test/setupTests.ts b/apps/web/src/test/setupTests.ts index 9f2125dba6..cbb6a4386d 100644 --- a/apps/web/src/test/setupTests.ts +++ b/apps/web/src/test/setupTests.ts @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE files in the repository root for full details. */ -import { beforeEach, afterEach } from "vitest"; +import { vi, beforeEach, afterEach } from "vitest"; import fetchMock, { manageFetchMockGlobally } from "@fetch-mock/vitest"; import SdkConfig, { DEFAULTS } from "../SdkConfig"; @@ -15,6 +15,8 @@ import { setupLanguageMock } from "./setupLanguage.ts"; manageFetchMockGlobally(); beforeEach(() => { + vi.stubEnv("TZ", "UTC"); + // set up fetch API mock fetchMock.hardReset(); fetchMock.catch(404); diff --git a/apps/web/test/unit-tests/utils/ErrorUtils-test.ts b/apps/web/src/utils/ErrorUtils.test.ts similarity index 97% rename from apps/web/test/unit-tests/utils/ErrorUtils-test.ts rename to apps/web/src/utils/ErrorUtils.test.ts index 170a639af3..c1dd43ea82 100644 --- a/apps/web/test/unit-tests/utils/ErrorUtils-test.ts +++ b/apps/web/src/utils/ErrorUtils.test.ts @@ -6,8 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com Please see LICENSE files in the repository root for full details. */ +// @vitest-environment happy-dom + import { type ReactElement } from "react"; -import { render } from "jest-matrix-react"; +import { render } from "test-utils-rtl"; +import { describe, it, expect } from "vitest"; import { MatrixError, ConnectionError } from "matrix-js-sdk/src/matrix"; import { @@ -17,7 +20,7 @@ import { messageForResourceLimitError, messageForSyncError, resourceLimitStrings, -} from "../../../src/utils/ErrorUtils"; +} from "./ErrorUtils"; describe("messageForResourceLimitError", () => { it("should match snapshot for monthly_active_user", () => { diff --git a/apps/web/test/unit-tests/utils/EventUtils-test.ts b/apps/web/src/utils/EventUtils.test.ts similarity index 94% rename from apps/web/test/unit-tests/utils/EventUtils-test.ts rename to apps/web/src/utils/EventUtils.test.ts index fc5648e7f0..f365b4f289 100644 --- a/apps/web/test/unit-tests/utils/EventUtils-test.ts +++ b/apps/web/src/utils/EventUtils.test.ts @@ -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. */ +// @vitest-environment happy-dom + import { M_LOCATION, EventStatus, @@ -19,8 +21,9 @@ import { Room, Thread, } from "matrix-js-sdk/src/matrix"; +import { vi, describe, it, expect, beforeEach, afterAll } from "vitest"; -import { MatrixClientPeg } from "../../../src/MatrixClientPeg"; +import { MatrixClientPeg } from "../MatrixClientPeg"; import { canCancel, canEditContent, @@ -31,25 +34,30 @@ import { isContentActionable, isLocationEvent, isVoiceMessage, -} from "../../../src/utils/EventUtils"; -import { getMockClientWithEventEmitter, makeBeaconInfoEvent, makePollStartEvent, stubClient } from "../../test-utils"; -import dis from "../../../src/dispatcher/dispatcher"; -import { Action } from "../../../src/dispatcher/actions"; +} from "./EventUtils"; +import { + getMockClientWithEventEmitter, + makeBeaconInfoEvent, + makePollStartEvent, + stubClient, +} from "../../test/test-utils"; +import dis from "../dispatcher/dispatcher"; +import { Action } from "../dispatcher/actions"; -jest.mock("../../../src/dispatcher/dispatcher"); +vi.mock("../dispatcher/dispatcher"); describe("EventUtils", () => { const userId = "@user:server"; const roomId = "!room:server"; const mockClient = getMockClientWithEventEmitter({ - getUserId: jest.fn().mockReturnValue(userId), + getUserId: vi.fn().mockReturnValue(userId), }); beforeEach(() => { mockClient.getUserId.mockClear().mockReturnValue(userId); }); afterAll(() => { - jest.spyOn(MatrixClientPeg, "get").mockRestore(); + vi.spyOn(MatrixClientPeg, "get").mockRestore(); }); // setup events @@ -404,7 +412,7 @@ describe("EventUtils", () => { }; beforeEach(() => { - jest.clearAllMocks(); + vi.clearAllMocks(); stubClient(); client = MatrixClientPeg.safeGet(); @@ -413,9 +421,9 @@ describe("EventUtils", () => { pendingEventOrdering: PendingEventOrdering.Detached, }); - jest.spyOn(client, "supportsThreads").mockReturnValue(true); - jest.spyOn(client, "getRoom").mockReturnValue(room); - jest.spyOn(client, "fetchRoomEvent").mockImplementation(async (roomId, eventId) => { + vi.spyOn(client, "supportsThreads").mockReturnValue(true); + vi.spyOn(client, "getRoom").mockReturnValue(room); + vi.spyOn(client, "fetchRoomEvent").mockImplementation(async (roomId, eventId) => { return events[eventId] ?? Promise.reject(); }); }); diff --git a/apps/web/test/unit-tests/utils/FileUtils-test.ts b/apps/web/src/utils/FileUtils.test.ts similarity index 94% rename from apps/web/test/unit-tests/utils/FileUtils-test.ts rename to apps/web/src/utils/FileUtils.test.ts index 68e0c3ae06..b2e9c6d232 100644 --- a/apps/web/test/unit-tests/utils/FileUtils-test.ts +++ b/apps/web/src/utils/FileUtils.test.ts @@ -6,8 +6,9 @@ Please see LICENSE files in the repository root for full details. */ import { type MediaEventContent } from "matrix-js-sdk/src/types"; +import { describe, it, expect } from "vitest"; -import { downloadLabelForFile } from "../../../src/utils/FileUtils.ts"; +import { downloadLabelForFile } from "./FileUtils.ts"; describe("FileUtils", () => { describe("downloadLabelForFile", () => { diff --git a/apps/web/test/unit-tests/utils/__snapshots__/ErrorUtils-test.ts.snap b/apps/web/src/utils/__snapshots__/ErrorUtils.test.ts.snap similarity index 72% rename from apps/web/test/unit-tests/utils/__snapshots__/ErrorUtils-test.ts.snap rename to apps/web/src/utils/__snapshots__/ErrorUtils.test.ts.snap index 6c8cc750b8..0128ca2e56 100644 --- a/apps/web/test/unit-tests/utils/__snapshots__/ErrorUtils-test.ts.snap +++ b/apps/web/src/utils/__snapshots__/ErrorUtils.test.ts.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html -exports[`messageForConnectionError should match snapshot for ConnectionError 1`] = ` +exports[`messageForConnectionError > should match snapshot for ConnectionError 1`] = ` @@ -34,13 +34,13 @@ exports[`messageForConnectionError should match snapshot for ConnectionError 1`] `; -exports[`messageForConnectionError should match snapshot for MatrixError M_NOT_FOUND 1`] = ` +exports[`messageForConnectionError > should match snapshot for MatrixError M_NOT_FOUND 1`] = ` There was a problem communicating with the homeserver, please try again later.(M_NOT_FOUND) `; -exports[`messageForConnectionError should match snapshot for mixed content error 1`] = ` +exports[`messageForConnectionError > should match snapshot for mixed content error 1`] = ` @@ -58,19 +58,19 @@ exports[`messageForConnectionError should match snapshot for mixed content error `; -exports[`messageForConnectionError should match snapshot for unknown error 1`] = ` +exports[`messageForConnectionError > should match snapshot for unknown error 1`] = ` There was a problem communicating with the homeserver, please try again later. `; -exports[`messageForLoginError should match snapshot for 401 1`] = ` +exports[`messageForLoginError > should match snapshot for 401 1`] = ` Incorrect username and/or password. `; -exports[`messageForLoginError should match snapshot for M_RESOURCE_LIMIT_EXCEEDED 1`] = ` +exports[`messageForLoginError > should match snapshot for M_RESOURCE_LIMIT_EXCEEDED 1`] = `
@@ -85,19 +85,19 @@ exports[`messageForLoginError should match snapshot for M_RESOURCE_LIMIT_EXCEEDE `; -exports[`messageForLoginError should match snapshot for M_USER_DEACTIVATED 1`] = ` +exports[`messageForLoginError > should match snapshot for M_USER_DEACTIVATED 1`] = ` This account has been deactivated. `; -exports[`messageForLoginError should match snapshot for unknown error 1`] = ` +exports[`messageForLoginError > should match snapshot for unknown error 1`] = ` There was a problem communicating with the homeserver, please try again later. (HTTP 400) `; -exports[`messageForResourceLimitError should match snapshot for admin contact links 1`] = ` +exports[`messageForResourceLimitError > should match snapshot for admin contact links 1`] = ` Please @@ -113,13 +113,13 @@ exports[`messageForResourceLimitError should match snapshot for admin contact li `; -exports[`messageForResourceLimitError should match snapshot for monthly_active_user 1`] = ` +exports[`messageForResourceLimitError > should match snapshot for monthly_active_user 1`] = ` This homeserver has hit its Monthly Active User limit. `; -exports[`messageForSyncError should match snapshot for M_RESOURCE_LIMIT_EXCEEDED 1`] = ` +exports[`messageForSyncError > should match snapshot for M_RESOURCE_LIMIT_EXCEEDED 1`] = `
@@ -132,7 +132,7 @@ exports[`messageForSyncError should match snapshot for M_RESOURCE_LIMIT_EXCEEDED `; -exports[`messageForSyncError should match snapshot for other errors 1`] = ` +exports[`messageForSyncError > should match snapshot for other errors 1`] = `
Unable to connect to Homeserver. Retrying… diff --git a/apps/web/test/unit-tests/utils/leave-behaviour-test.ts b/apps/web/src/utils/leave-behaviour.test.ts similarity index 74% rename from apps/web/test/unit-tests/utils/leave-behaviour-test.ts rename to apps/web/src/utils/leave-behaviour.test.ts index 334e518e5f..929d6ebfa4 100644 --- a/apps/web/test/unit-tests/utils/leave-behaviour-test.ts +++ b/apps/web/src/utils/leave-behaviour.test.ts @@ -6,25 +6,29 @@ 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-vitest-adapter"; +// @vitest-environment happy-dom + +import { vi, describe, it, expect, beforeEach, afterEach, type Mocked } from "vitest"; import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix"; import { sleep } from "matrix-js-sdk/src/utils"; +import { mkRoom, resetAsyncStoreWithClient, setupAsyncStoreWithClient, stubClient } from "test-utils/test-utils"; -import { MatrixClientPeg } from "../../../src/MatrixClientPeg"; -import { mkRoom, resetAsyncStoreWithClient, setupAsyncStoreWithClient, stubClient } from "../../test-utils"; -import defaultDispatcher from "../../../src/dispatcher/dispatcher"; -import { type ViewRoomPayload } from "../../../src/dispatcher/payloads/ViewRoomPayload"; -import { Action } from "../../../src/dispatcher/actions"; -import { leaveRoomBehaviour } from "../../../src/utils/leave-behaviour"; -import { SDKContextClass } from "../../../src/contexts/SDKContextClass"; -import DMRoomMap from "../../../src/utils/DMRoomMap"; -import SpaceStore from "../../../src/stores/spaces/SpaceStore"; -import { MetaSpace } from "../../../src/stores/spaces"; -import { type ActionPayload } from "../../../src/dispatcher/payloads"; -import SettingsStore from "../../../src/settings/SettingsStore"; -import { CallStore } from "../../../src/stores/CallStore"; -import { type Call } from "../../../src/models/Call"; -import LegacyCallHandler from "../../../src/LegacyCallHandler"; +import { MatrixClientPeg } from "../MatrixClientPeg"; +import defaultDispatcher from "../dispatcher/dispatcher"; +import { type ViewRoomPayload } from "../dispatcher/payloads/ViewRoomPayload"; +import { Action } from "../dispatcher/actions"; +import { leaveRoomBehaviour } from "./leave-behaviour"; +import { SDKContextClass } from "../contexts/SDKContextClass"; +import DMRoomMap from "../utils/DMRoomMap"; +import SpaceStore from "../stores/spaces/SpaceStore"; +import { MetaSpace } from "../stores/spaces"; +import { type ActionPayload } from "../dispatcher/payloads"; +import SettingsStore from "../settings/SettingsStore"; +import { CallStore } from "../stores/CallStore"; +import { type Call } from "../models/Call"; +import LegacyCallHandler from "../LegacyCallHandler"; + +vi.mock("../Modal.tsx"); describe("leaveRoomBehaviour", () => { SDKContextClass.instance.constructEagerStores(); // Initialize RoomViewStore @@ -35,7 +39,7 @@ describe("leaveRoomBehaviour", () => { beforeEach(async () => { stubClient(); - client = mocked(MatrixClientPeg.safeGet()); + client = vi.mocked(MatrixClientPeg.safeGet()); DMRoomMap.makeShared(client); room = mkRoom(client, "!1:example.org"); @@ -58,7 +62,7 @@ describe("leaveRoomBehaviour", () => { afterEach(async () => { SpaceStore.instance.setActiveSpace(MetaSpace.Home); await resetAsyncStoreWithClient(SpaceStore.instance); - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); const viewRoom = (room: Room) => @@ -72,7 +76,7 @@ describe("leaveRoomBehaviour", () => { ); const expectDispatch = async (payload: T) => { - const dispatcherSpy = jest.fn(); + const dispatcherSpy = vi.fn(); const dispatcherRef = defaultDispatcher.register(dispatcherSpy); await sleep(0); expect(dispatcherSpy).toHaveBeenCalledWith(payload); @@ -80,7 +84,7 @@ describe("leaveRoomBehaviour", () => { }; it("hangs up legacy calls when leaving a room", async () => { - const hangupSpy = jest.spyOn(LegacyCallHandler.instance, "hangupOrReject").mockImplementation(() => {}); + const hangupSpy = vi.spyOn(LegacyCallHandler.instance, "hangupOrReject").mockImplementation(() => {}); viewRoom(room); await leaveRoomBehaviour(client, room.roomId); @@ -90,10 +94,10 @@ describe("leaveRoomBehaviour", () => { it("disconnects widget-based calls when leaving a room", async () => { const mockCall = { - disconnect: jest.fn().mockResolvedValue(undefined), + disconnect: vi.fn().mockResolvedValue(undefined), } as unknown as Call; - jest.spyOn(CallStore.instance, "getActiveCall").mockReturnValue(mockCall); + vi.spyOn(CallStore.instance, "getActiveCall").mockReturnValue(mockCall); viewRoom(room); await leaveRoomBehaviour(client, room.roomId); @@ -109,7 +113,7 @@ describe("leaveRoomBehaviour", () => { }); it("returns to the parent space after leaving a room inside of a space that was being viewed", async () => { - jest.spyOn(SpaceStore.instance, "getCanonicalParent").mockImplementation((roomId) => + vi.spyOn(SpaceStore.instance, "getCanonicalParent").mockImplementation((roomId) => roomId === room.roomId ? space : null, ); viewRoom(room); @@ -133,7 +137,7 @@ describe("leaveRoomBehaviour", () => { it("returns to the parent space after leaving a subspace that was being viewed", async () => { room.isSpaceRoom.mockReturnValue(true); - jest.spyOn(SpaceStore.instance, "getCanonicalParent").mockImplementation((roomId) => + vi.spyOn(SpaceStore.instance, "getCanonicalParent").mockImplementation((roomId) => roomId === room.roomId ? space : null, ); viewRoom(room); @@ -149,7 +153,7 @@ describe("leaveRoomBehaviour", () => { describe("If the feature_dynamic_room_predecessors is not enabled", () => { beforeEach(() => { - jest.spyOn(SettingsStore, "getValue").mockReturnValue(false); + vi.spyOn(SettingsStore, "getValue").mockReturnValue(false); }); it("Passes through the dynamic predecessor setting", async () => { @@ -161,7 +165,7 @@ describe("leaveRoomBehaviour", () => { describe("If the feature_dynamic_room_predecessors is enabled", () => { beforeEach(() => { // Turn on feature_dynamic_room_predecessors setting - jest.spyOn(SettingsStore, "getValue").mockImplementation( + vi.spyOn(SettingsStore, "getValue").mockImplementation( (settingName) => settingName === "feature_dynamic_room_predecessors", ); }); diff --git a/apps/web/test/viewmodels/room/WidgetPip-test.ts b/apps/web/src/viewmodels/room/WidgetPipViewModel.test.ts similarity index 71% rename from apps/web/test/viewmodels/room/WidgetPip-test.ts rename to apps/web/src/viewmodels/room/WidgetPipViewModel.test.ts index 714a61ad39..646ee476b5 100644 --- a/apps/web/test/viewmodels/room/WidgetPip-test.ts +++ b/apps/web/src/viewmodels/room/WidgetPipViewModel.test.ts @@ -5,18 +5,20 @@ * Please see LICENSE files in the repository root for full details. */ -import { type MatrixClient, type Room, RoomEvent } from "matrix-js-sdk/src/matrix"; -import { type MockedObject } from "jest-mock-vitest-adapter"; -import { createRef } from "react"; +// @vitest-environment happy-dom -import { mkRoom, stubClient } from "../../test-utils"; -import { WidgetPipViewModel } from "../../../src/viewmodels/room/WidgetPipViewModel"; -import WidgetStore, { type IApp } from "../../../src/stores/WidgetStore"; -import defaultDispatcher from "../../../src/dispatcher/dispatcher"; -import { Action } from "../../../src/dispatcher/actions"; -import { WidgetLayoutStore } from "../../../src/stores/widgets/WidgetLayoutStore"; -import { CallStore, CallStoreEvent } from "../../../src/stores/CallStore"; -import { type Call } from "../../../src/models/Call"; +import { type MatrixClient, type Room, RoomEvent } from "matrix-js-sdk/src/matrix"; +import { vi, describe, it, expect, beforeEach, afterEach, type MockedObject } from "vitest"; +import { createRef } from "react"; +import { mkRoom, stubClient } from "test-utils"; + +import { WidgetPipViewModel } from "./WidgetPipViewModel"; +import WidgetStore, { type IApp } from "../../stores/WidgetStore"; +import defaultDispatcher from "../../dispatcher/dispatcher"; +import { Action } from "../../dispatcher/actions"; +import { WidgetLayoutStore } from "../../stores/widgets/WidgetLayoutStore"; +import { CallStore, CallStoreEvent } from "../../stores/CallStore"; +import { type Call } from "../../models/Call"; const userId = "@example:example.org"; const widgetId = "test-widget-id"; @@ -25,8 +27,8 @@ type BackClickEvent = Parameters[0]; const createBackClickEvent = (): BackClickEvent => ({ - preventDefault: jest.fn(), - stopPropagation: jest.fn(), + preventDefault: vi.fn(), + stopPropagation: vi.fn(), }) as unknown as BackClickEvent; describe("WidgetPipViewModel", () => { @@ -46,7 +48,7 @@ describe("WidgetPipViewModel", () => { name: "Test Widget", data: {}, } as unknown as IApp; - jest.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]); + vi.spyOn(WidgetStore.instance, "getApps").mockReturnValue([widget]); vm = new WidgetPipViewModel({ room, @@ -58,7 +60,7 @@ describe("WidgetPipViewModel", () => { afterEach(() => { vm.dispose(); - jest.restoreAllMocks(); + vi.restoreAllMocks(); }); it("updates room name", () => { @@ -68,7 +70,7 @@ describe("WidgetPipViewModel", () => { }); it("updates onBackClick if call changes", () => { - const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch").mockImplementation(() => {}); + const dispatchSpy = vi.spyOn(defaultDispatcher, "dispatch").mockImplementation(() => {}); vm.onBackClick(createBackClickEvent()); expect(dispatchSpy).toHaveBeenCalledWith({ @@ -91,8 +93,8 @@ describe("WidgetPipViewModel", () => { }); it("updates onBackClick if viewingRoom changes", () => { - const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch").mockImplementation(() => {}); - const moveSpy = jest.spyOn(WidgetLayoutStore.instance, "moveToContainer").mockImplementation(() => {}); + const dispatchSpy = vi.spyOn(defaultDispatcher, "dispatch").mockImplementation(() => {}); + const moveSpy = vi.spyOn(WidgetLayoutStore.instance, "moveToContainer").mockImplementation(() => {}); vm.setViewingRoom(true); vm.onBackClick(createBackClickEvent()); diff --git a/apps/web/test/test-utils/jest-matrix-react.tsx b/apps/web/test/test-utils/jest-matrix-react.tsx index 76150df478..f9009b73f6 100644 --- a/apps/web/test/test-utils/jest-matrix-react.tsx +++ b/apps/web/test/test-utils/jest-matrix-react.tsx @@ -10,7 +10,9 @@ import React, { type ReactElement } from "react"; // eslint-disable-next-line no-restricted-imports import { render, type RenderOptions } from "@testing-library/react"; import { TooltipProvider } from "@vector-im/compound-web"; -import { I18nContext } from "@element-hq/web-shared-components"; +import { I18nApi, I18nContext } from "@element-hq/web-shared-components"; + +const i18nApi = new I18nApi(); /** * Wraps the provided components in: @@ -26,7 +28,7 @@ const wrapWithStandardContexts = (Wrapper: RenderOptions["wrapper"]) => { if (Wrapper) { return ( - + {children} @@ -34,7 +36,7 @@ const wrapWithStandardContexts = (Wrapper: RenderOptions["wrapper"]) => { } else { return ( - {children} + {children} ); }