Migrate more tests to vitest (#34349)
This commit is contained in:
+19
-15
@@ -6,12 +6,16 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { HTTPError, type MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked } from "jest-mock";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { createCrossSigning } from "../src/CreateCrossSigning";
|
||||
import { createTestClient } from "./test-utils";
|
||||
import Modal from "../src/Modal";
|
||||
import { vi, describe, it, expect, beforeEach } from "vitest";
|
||||
import { HTTPError, type MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
|
||||
import { createTestClient } from "test-utils";
|
||||
|
||||
import { createCrossSigning } from "./CreateCrossSigning";
|
||||
import Modal from "./Modal";
|
||||
|
||||
vi.mock("./Modal");
|
||||
|
||||
describe("CreateCrossSigning", () => {
|
||||
let client: MatrixClient;
|
||||
@@ -29,7 +33,7 @@ describe("CreateCrossSigning", () => {
|
||||
});
|
||||
|
||||
it("should upload", async () => {
|
||||
client.uploadDeviceSigningKeys = jest.fn().mockRejectedValueOnce(
|
||||
client.uploadDeviceSigningKeys = vi.fn().mockRejectedValueOnce(
|
||||
new MatrixError({
|
||||
flows: [
|
||||
{
|
||||
@@ -41,20 +45,20 @@ describe("CreateCrossSigning", () => {
|
||||
|
||||
await createCrossSigning(client);
|
||||
|
||||
const { authUploadDeviceSigningKeys } = mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
const { authUploadDeviceSigningKeys } = vi.mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
|
||||
const makeRequest = jest.fn();
|
||||
const makeRequest = vi.fn();
|
||||
await authUploadDeviceSigningKeys!(makeRequest);
|
||||
expect(makeRequest).toHaveBeenCalledWith(null);
|
||||
});
|
||||
|
||||
it("should prompt user if upload failed with UIA", async () => {
|
||||
const createDialog = jest.spyOn(Modal, "createDialog").mockReturnValue({
|
||||
const createDialog = vi.spyOn(Modal, "createDialog").mockReturnValue({
|
||||
finished: Promise.resolve([true]),
|
||||
close: jest.fn(),
|
||||
close: vi.fn(),
|
||||
});
|
||||
|
||||
client.uploadDeviceSigningKeys = jest.fn().mockRejectedValueOnce(
|
||||
client.uploadDeviceSigningKeys = vi.fn().mockRejectedValueOnce(
|
||||
new MatrixError({
|
||||
flows: [
|
||||
{
|
||||
@@ -66,9 +70,9 @@ describe("CreateCrossSigning", () => {
|
||||
|
||||
await createCrossSigning(client);
|
||||
|
||||
const { authUploadDeviceSigningKeys } = mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
const { authUploadDeviceSigningKeys } = vi.mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
|
||||
const makeRequest = jest.fn().mockRejectedValue(
|
||||
const makeRequest = vi.fn().mockRejectedValue(
|
||||
new MatrixError({
|
||||
flows: [
|
||||
{
|
||||
@@ -85,10 +89,10 @@ describe("CreateCrossSigning", () => {
|
||||
it("should throw error if server fails with something other than UIA", async () => {
|
||||
await createCrossSigning(client);
|
||||
|
||||
const { authUploadDeviceSigningKeys } = mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
const { authUploadDeviceSigningKeys } = vi.mocked(client.getCrypto()!).bootstrapCrossSigning.mock.calls[0][0];
|
||||
|
||||
const error = new HTTPError("Internal Server Error", 500);
|
||||
const makeRequest = jest.fn().mockRejectedValue(error);
|
||||
const makeRequest = vi.fn().mockRejectedValue(error);
|
||||
await expect(authUploadDeviceSigningKeys!(makeRequest)).rejects.toThrow(error);
|
||||
expect(makeRequest).not.toHaveBeenCalledWith();
|
||||
});
|
||||
+16
-14
@@ -5,7 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked, type Mocked, type MockedObject } from "jest-mock";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, afterEach, type Mocked, type MockedObject } from "vitest";
|
||||
import { HttpApiEvent, type MatrixClient, type MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { decryptExistingEvent, mkDecryptionFailureMatrixEvent } from "matrix-js-sdk/src/testing";
|
||||
import {
|
||||
@@ -15,10 +17,10 @@ import {
|
||||
CryptoEvent,
|
||||
} from "matrix-js-sdk/src/crypto-api";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import { stubClient } from "test-utils";
|
||||
|
||||
import { DecryptionFailureTracker, type ErrorProperties } from "../../src/DecryptionFailureTracker";
|
||||
import { stubClient } from "../test-utils";
|
||||
import * as Lifecycle from "../../src/Lifecycle";
|
||||
import { DecryptionFailureTracker, type ErrorProperties } from "./DecryptionFailureTracker";
|
||||
import * as Lifecycle from "./Lifecycle";
|
||||
|
||||
async function createFailedDecryptionEvent(opts: { sender?: string; code?: DecryptionFailureCode } = {}) {
|
||||
return await mkDecryptionFailureMatrixEvent({
|
||||
@@ -592,7 +594,7 @@ describe("DecryptionFailureTracker", function () {
|
||||
// Calling .start will start some intervals. This test shouldn't run
|
||||
// long enough for the timers to fire, but we'll use fake timers just
|
||||
// to be safe.
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
await tracker.start(client);
|
||||
|
||||
// If the client fails to decrypt, it should get tracked
|
||||
@@ -616,7 +618,7 @@ describe("DecryptionFailureTracker", function () {
|
||||
|
||||
expect(errorCount).toEqual(1);
|
||||
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("tracks client information", async () => {
|
||||
@@ -657,7 +659,7 @@ describe("DecryptionFailureTracker", function () {
|
||||
const now = Date.now();
|
||||
eventDecrypted(tracker, federatedDecryption, now);
|
||||
|
||||
mocked(client.getCrypto()!.getUserVerificationStatus).mockResolvedValue(
|
||||
vi.mocked(client.getCrypto()!.getUserVerificationStatus).mockResolvedValue(
|
||||
new UserVerificationStatus(true, true, false),
|
||||
);
|
||||
client.emit(CryptoEvent.KeysChanged, {});
|
||||
@@ -677,7 +679,7 @@ describe("DecryptionFailureTracker", function () {
|
||||
|
||||
// change client params, and make sure the reports the right values
|
||||
client.getDomain.mockReturnValue("example.com");
|
||||
mocked(client.getCrypto()!.getVersion).mockReturnValue("Olm 0.0.0");
|
||||
vi.mocked(client.getCrypto()!.getVersion).mockReturnValue("Olm 0.0.0");
|
||||
// @ts-ignore access to private method
|
||||
await tracker.calculateClientProperties(client);
|
||||
|
||||
@@ -725,19 +727,19 @@ describe("DecryptionFailureTracker", function () {
|
||||
});
|
||||
|
||||
function mockClient(): MockedObject<MatrixClient> {
|
||||
const client = mocked(stubClient());
|
||||
const client = vi.mocked(stubClient());
|
||||
const mockCrypto = {
|
||||
getVersion: jest.fn().mockReturnValue("Rust SDK 0.7.0 (61b175b), Vodozemac 0.5.1"),
|
||||
getUserVerificationStatus: jest.fn().mockResolvedValue(new UserVerificationStatus(false, false, false)),
|
||||
getVersion: vi.fn().mockReturnValue("Rust SDK 0.7.0 (61b175b), Vodozemac 0.5.1"),
|
||||
getUserVerificationStatus: vi.fn().mockResolvedValue(new UserVerificationStatus(false, false, false)),
|
||||
} as unknown as Mocked<CryptoApi>;
|
||||
client.getCrypto.mockReturnValue(mockCrypto);
|
||||
|
||||
// @ts-ignore
|
||||
client.stopClient = jest.fn(() => {});
|
||||
client.stopClient = vi.fn(() => {});
|
||||
// @ts-ignore
|
||||
client.removeAllListeners = jest.fn(() => {});
|
||||
client.removeAllListeners = vi.fn(() => {});
|
||||
|
||||
client.store = { destroy: jest.fn(() => {}) } as any;
|
||||
client.store = { destroy: vi.fn(() => {}) } as any;
|
||||
|
||||
return client;
|
||||
}
|
||||
+93
-89
@@ -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 { type Mocked, mocked } from "jest-mock-vitest-adapter";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, beforeEach, type Mocked } from "vitest";
|
||||
import {
|
||||
MatrixEvent,
|
||||
type Room,
|
||||
@@ -24,38 +26,40 @@ import {
|
||||
type SecretStorageStatus,
|
||||
} from "matrix-js-sdk/src/crypto-api";
|
||||
import { type CryptoSessionStateChange } from "@matrix-org/analytics-events/types/typescript/CryptoSessionStateChange";
|
||||
import { getMockClientWithEventEmitter, mockPlatformPeg } from "test-utils";
|
||||
|
||||
import {
|
||||
DeviceListener,
|
||||
ACCOUNT_DATA_KEY_M_KEY_BACKUP,
|
||||
ACCOUNT_DATA_KEY_M_KEY_BACKUP_DISABLED_UNSTABLE,
|
||||
RECOVERY_ACCOUNT_DATA_KEY,
|
||||
} from "../../src/device-listener";
|
||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||
import * as SetupEncryptionToast from "../../src/toasts/SetupEncryptionToast";
|
||||
import * as UnverifiedSessionToast from "../../src/toasts/UnverifiedSessionToast";
|
||||
import * as BulkUnverifiedSessionsToast from "../../src/toasts/BulkUnverifiedSessionsToast";
|
||||
import { isSecretStorageBeingAccessed } from "../../src/SecurityManager";
|
||||
import { Action } from "../../src/dispatcher/actions";
|
||||
import SettingsStore from "../../src/settings/SettingsStore";
|
||||
import { SettingLevel } from "../../src/settings/SettingLevel";
|
||||
import { getMockClientWithEventEmitter, mockPlatformPeg } from "../test-utils";
|
||||
import { isBulkUnverifiedDeviceReminderSnoozed } from "../../src/utils/device/snoozeBulkUnverifiedDeviceReminder";
|
||||
import { PosthogAnalytics } from "../../src/PosthogAnalytics";
|
||||
} from "./device-listener";
|
||||
import { MatrixClientPeg } from "./MatrixClientPeg";
|
||||
import * as SetupEncryptionToast from "./toasts/SetupEncryptionToast";
|
||||
import * as UnverifiedSessionToast from "./toasts/UnverifiedSessionToast";
|
||||
import * as BulkUnverifiedSessionsToast from "./toasts/BulkUnverifiedSessionsToast";
|
||||
import { isSecretStorageBeingAccessed } from "./SecurityManager";
|
||||
import { Action } from "./dispatcher/actions";
|
||||
import SettingsStore from "./settings/SettingsStore";
|
||||
import { SettingLevel } from "./settings/SettingLevel";
|
||||
import { isBulkUnverifiedDeviceReminderSnoozed } from "./utils/device/snoozeBulkUnverifiedDeviceReminder";
|
||||
import { PosthogAnalytics } from "./PosthogAnalytics";
|
||||
|
||||
jest.mock("../../src/dispatcher/dispatcher", () => ({
|
||||
dispatch: jest.fn(),
|
||||
register: jest.fn(),
|
||||
unregister: jest.fn(),
|
||||
vi.mock("./dispatcher/dispatcher", () => ({
|
||||
default: {
|
||||
dispatch: vi.fn(),
|
||||
register: vi.fn(),
|
||||
unregister: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock("../../src/SecurityManager", () => ({
|
||||
isSecretStorageBeingAccessed: jest.fn(),
|
||||
accessSecretStorage: jest.fn(),
|
||||
vi.mock("./SecurityManager", () => ({
|
||||
isSecretStorageBeingAccessed: vi.fn(),
|
||||
accessSecretStorage: vi.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../../src/utils/device/snoozeBulkUnverifiedDeviceReminder", () => ({
|
||||
isBulkUnverifiedDeviceReminderSnoozed: jest.fn(),
|
||||
vi.mock("./utils/device/snoozeBulkUnverifiedDeviceReminder", () => ({
|
||||
isBulkUnverifiedDeviceReminderSnoozed: vi.fn(),
|
||||
}));
|
||||
|
||||
const userId = "@user:server";
|
||||
@@ -79,36 +83,36 @@ describe("DeviceListener", () => {
|
||||
let mockCrypto: Mocked<CryptoApi>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
vi.resetAllMocks();
|
||||
|
||||
// don't litter the console with logs
|
||||
jest.spyOn(console, "debug").mockImplementation(() => {});
|
||||
jest.spyOn(console, "info").mockImplementation(() => {});
|
||||
jest.spyOn(console, "warn").mockImplementation(() => {});
|
||||
jest.spyOn(console, "error").mockImplementation(() => {});
|
||||
vi.spyOn(console, "debug").mockImplementation(() => {});
|
||||
vi.spyOn(console, "info").mockImplementation(() => {});
|
||||
vi.spyOn(console, "warn").mockImplementation(() => {});
|
||||
vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
|
||||
// spy on various toasts' hide and show functions
|
||||
// easier than mocking
|
||||
jest.spyOn(SetupEncryptionToast, "showToast").mockReturnValue(undefined);
|
||||
jest.spyOn(SetupEncryptionToast, "hideToast").mockReturnValue(undefined);
|
||||
jest.spyOn(BulkUnverifiedSessionsToast, "showToast").mockReturnValue(undefined);
|
||||
jest.spyOn(BulkUnverifiedSessionsToast, "hideToast").mockReturnValue(undefined);
|
||||
jest.spyOn(UnverifiedSessionToast, "showToast").mockResolvedValue(undefined);
|
||||
jest.spyOn(UnverifiedSessionToast, "hideToast").mockReturnValue(undefined);
|
||||
vi.spyOn(SetupEncryptionToast, "showToast").mockReturnValue(undefined);
|
||||
vi.spyOn(SetupEncryptionToast, "hideToast").mockReturnValue(undefined);
|
||||
vi.spyOn(BulkUnverifiedSessionsToast, "showToast").mockReturnValue(undefined);
|
||||
vi.spyOn(BulkUnverifiedSessionsToast, "hideToast").mockReturnValue(undefined);
|
||||
vi.spyOn(UnverifiedSessionToast, "showToast").mockResolvedValue(undefined);
|
||||
vi.spyOn(UnverifiedSessionToast, "hideToast").mockReturnValue(undefined);
|
||||
|
||||
mockPlatformPeg({
|
||||
getAppVersion: jest.fn().mockResolvedValue("1.2.3"),
|
||||
getAppVersion: vi.fn().mockResolvedValue("1.2.3"),
|
||||
});
|
||||
mockCrypto = {
|
||||
getDeviceVerificationStatus: jest.fn().mockResolvedValue({
|
||||
getDeviceVerificationStatus: vi.fn().mockResolvedValue({
|
||||
crossSigningVerified: false,
|
||||
}),
|
||||
getUserDeviceInfo: jest.fn().mockResolvedValue(new Map()),
|
||||
isCrossSigningReady: jest.fn().mockResolvedValue(true),
|
||||
getSecretStorageStatus: jest.fn().mockResolvedValue(readySecretStorageStatus),
|
||||
userHasCrossSigningKeys: jest.fn(),
|
||||
getActiveSessionBackupVersion: jest.fn(),
|
||||
getCrossSigningStatus: jest.fn().mockReturnValue({
|
||||
getUserDeviceInfo: vi.fn().mockResolvedValue(new Map()),
|
||||
isCrossSigningReady: vi.fn().mockResolvedValue(true),
|
||||
getSecretStorageStatus: vi.fn().mockResolvedValue(readySecretStorageStatus),
|
||||
userHasCrossSigningKeys: vi.fn(),
|
||||
getActiveSessionBackupVersion: vi.fn(),
|
||||
getCrossSigningStatus: vi.fn().mockReturnValue({
|
||||
publicKeysOnDevice: true,
|
||||
privateKeysInSecretStorage: true,
|
||||
privateKeysCachedLocally: {
|
||||
@@ -117,33 +121,33 @@ describe("DeviceListener", () => {
|
||||
userSigningKey: true,
|
||||
},
|
||||
}),
|
||||
getSessionBackupPrivateKey: jest.fn(),
|
||||
isEncryptionEnabledInRoom: jest.fn(),
|
||||
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
|
||||
getSessionBackupPrivateKey: vi.fn(),
|
||||
isEncryptionEnabledInRoom: vi.fn(),
|
||||
getKeyBackupInfo: vi.fn().mockResolvedValue(null),
|
||||
} as unknown as Mocked<CryptoApi>;
|
||||
mockClient = getMockClientWithEventEmitter({
|
||||
isGuest: jest.fn(),
|
||||
getUserId: jest.fn().mockReturnValue(userId),
|
||||
getSafeUserId: jest.fn().mockReturnValue(userId),
|
||||
getRooms: jest.fn().mockReturnValue([]),
|
||||
isVersionSupported: jest.fn().mockResolvedValue(true),
|
||||
isInitialSyncComplete: jest.fn().mockReturnValue(true),
|
||||
isKeyBackupKeyStored: jest.fn(),
|
||||
waitForClientWellKnown: jest.fn(),
|
||||
getClientWellKnown: jest.fn(),
|
||||
getDeviceId: jest.fn().mockReturnValue(deviceId),
|
||||
setAccountData: jest.fn(),
|
||||
getAccountData: jest.fn(),
|
||||
getAccountDataFromServer: jest.fn(),
|
||||
deleteAccountData: jest.fn(),
|
||||
getCrypto: jest.fn().mockReturnValue(mockCrypto),
|
||||
isGuest: vi.fn(),
|
||||
getUserId: vi.fn().mockReturnValue(userId),
|
||||
getSafeUserId: vi.fn().mockReturnValue(userId),
|
||||
getRooms: vi.fn().mockReturnValue([]),
|
||||
isVersionSupported: vi.fn().mockResolvedValue(true),
|
||||
isInitialSyncComplete: vi.fn().mockReturnValue(true),
|
||||
isKeyBackupKeyStored: vi.fn(),
|
||||
waitForClientWellKnown: vi.fn(),
|
||||
getClientWellKnown: vi.fn(),
|
||||
getDeviceId: vi.fn().mockReturnValue(deviceId),
|
||||
setAccountData: vi.fn(),
|
||||
getAccountData: vi.fn(),
|
||||
getAccountDataFromServer: vi.fn(),
|
||||
deleteAccountData: vi.fn(),
|
||||
getCrypto: vi.fn().mockReturnValue(mockCrypto),
|
||||
secretStorage: {
|
||||
isStored: jest.fn().mockReturnValue(null),
|
||||
isStored: vi.fn().mockReturnValue(null),
|
||||
},
|
||||
});
|
||||
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mockClient);
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
|
||||
mocked(isBulkUnverifiedDeviceReminderSnoozed).mockClear().mockReturnValue(false);
|
||||
vi.spyOn(MatrixClientPeg, "get").mockReturnValue(mockClient);
|
||||
vi.spyOn(SettingsStore, "getValue").mockReturnValue(false);
|
||||
vi.mocked(isBulkUnverifiedDeviceReminderSnoozed).mockClear().mockReturnValue(false);
|
||||
});
|
||||
|
||||
const createAndStart = async (): Promise<DeviceListener> => {
|
||||
@@ -155,8 +159,8 @@ describe("DeviceListener", () => {
|
||||
|
||||
describe("client information", () => {
|
||||
it("watches device client information setting", async () => {
|
||||
const watchSettingSpy = jest.spyOn(SettingsStore, "watchSetting");
|
||||
const unwatchSettingSpy = jest.spyOn(SettingsStore, "unwatchSetting");
|
||||
const watchSettingSpy = vi.spyOn(SettingsStore, "watchSetting");
|
||||
const unwatchSettingSpy = vi.spyOn(SettingsStore, "unwatchSetting");
|
||||
const deviceListener = await createAndStart();
|
||||
|
||||
expect(watchSettingSpy).toHaveBeenCalledWith("deviceClientInformationOptIn", null, expect.any(Function));
|
||||
@@ -168,7 +172,7 @@ describe("DeviceListener", () => {
|
||||
|
||||
it("responds to KeyBackupDecryptionKeyCached events", async () => {
|
||||
// Given a Device Listener
|
||||
const recheck = jest.fn();
|
||||
const recheck = vi.fn();
|
||||
const deviceListener = await createAndStart();
|
||||
deviceListener.recheck = recheck;
|
||||
|
||||
@@ -179,7 +183,7 @@ describe("DeviceListener", () => {
|
||||
expect(recheck).toHaveBeenCalled();
|
||||
|
||||
// And when we stop our device listener
|
||||
const removeListener = jest.fn(() => {});
|
||||
const removeListener = vi.fn(() => {});
|
||||
// @ts-ignore overwriting with a mock
|
||||
mockClient.removeListener = removeListener;
|
||||
deviceListener.stop();
|
||||
@@ -190,7 +194,7 @@ describe("DeviceListener", () => {
|
||||
|
||||
describe("when device client information feature is enabled", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
vi.spyOn(SettingsStore, "getValue").mockImplementation(
|
||||
(settingName) => settingName === "deviceClientInformationOptIn",
|
||||
);
|
||||
});
|
||||
@@ -241,7 +245,7 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
const emptyClientInfoEvent = new MatrixEvent({ type: `io.element.matrix_client_information.${deviceId}` });
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);
|
||||
vi.spyOn(SettingsStore, "getValue").mockReturnValue(false);
|
||||
|
||||
mockClient!.getAccountData.mockReturnValue(undefined);
|
||||
});
|
||||
@@ -280,7 +284,7 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
|
||||
it("saves client information after setting is enabled", async () => {
|
||||
const watchSettingSpy = jest.spyOn(SettingsStore, "watchSetting");
|
||||
const watchSettingSpy = vi.spyOn(SettingsStore, "watchSetting");
|
||||
await createAndStart();
|
||||
|
||||
const [settingName, roomId, callback] = watchSettingSpy.mock.calls[0];
|
||||
@@ -376,7 +380,7 @@ describe("DeviceListener", () => {
|
||||
mockCrypto!.isCrossSigningReady.mockResolvedValue(false);
|
||||
mockCrypto!.getSecretStorageStatus.mockResolvedValue(unreadySecretStorageStatus);
|
||||
mockClient!.getRooms.mockReturnValue(rooms);
|
||||
jest.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
|
||||
vi.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
|
||||
});
|
||||
|
||||
it("hides setup encryption toast when it is dismissed", async () => {
|
||||
@@ -392,27 +396,27 @@ describe("DeviceListener", () => {
|
||||
const instance = await createAndStart();
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledTimes(1);
|
||||
|
||||
jest.useFakeTimers({ advanceTimers: true });
|
||||
vi.useFakeTimers();
|
||||
instance.dismissEncryptionSetup();
|
||||
await flushPromises();
|
||||
expect(SetupEncryptionToast.hideToast).toHaveBeenCalled();
|
||||
|
||||
// 1.5 days after the toast was dismissed, we don't re-show the
|
||||
// toast yet.
|
||||
jest.advanceTimersByTime(1.5 * 24 * 60 * 60 * 1000);
|
||||
vi.advanceTimersByTime(1.5 * 24 * 60 * 60 * 1000);
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledTimes(1);
|
||||
|
||||
// 2 days after the toast was dismissed, we re-show the toast.
|
||||
jest.advanceTimersByTime(0.5 * 24 * 60 * 60 * 1000);
|
||||
vi.advanceTimersByTime(0.5 * 24 * 60 * 60 * 1000);
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledTimes(2);
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("doesn't re-show toast if the device is now verified", async () => {
|
||||
const instance = await createAndStart();
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledTimes(1);
|
||||
|
||||
jest.useFakeTimers({ advanceTimers: true });
|
||||
vi.useFakeTimers();
|
||||
instance.dismissEncryptionSetup();
|
||||
await flushPromises();
|
||||
expect(SetupEncryptionToast.hideToast).toHaveBeenCalled();
|
||||
@@ -427,20 +431,20 @@ describe("DeviceListener", () => {
|
||||
);
|
||||
instance.recheck();
|
||||
await flushPromises();
|
||||
jest.advanceTimersByTime(2 * 24 * 60 * 60 * 1000);
|
||||
vi.advanceTimersByTime(2 * 24 * 60 * 60 * 1000);
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledTimes(1);
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("does not show any toasts when secret storage is being accessed", async () => {
|
||||
mocked(isSecretStorageBeingAccessed).mockReturnValue(true);
|
||||
vi.mocked(isSecretStorageBeingAccessed).mockReturnValue(true);
|
||||
await createAndStart();
|
||||
|
||||
expect(SetupEncryptionToast.showToast).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("shows toasts even when no rooms are encrypted", async () => {
|
||||
jest.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(false);
|
||||
vi.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(false);
|
||||
await createAndStart();
|
||||
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalled();
|
||||
@@ -609,7 +613,7 @@ describe("DeviceListener", () => {
|
||||
// And we have run the checks once (and we were told to verify)
|
||||
const instance = await createAndStart();
|
||||
expect(SetupEncryptionToast.showToast).toHaveBeenCalledWith("verify_this_session");
|
||||
mocked(SetupEncryptionToast.showToast).mockClear();
|
||||
vi.mocked(SetupEncryptionToast.showToast).mockClear();
|
||||
mockCrypto.getDeviceVerificationStatus.mockClear();
|
||||
|
||||
// When we dismiss the dialog telling us to set up encryption
|
||||
@@ -672,7 +676,7 @@ describe("DeviceListener", () => {
|
||||
beforeEach(() => {
|
||||
// Encryption is in use
|
||||
mockClient.getRooms.mockReturnValue([{ roomId: "!room1" }, { roomId: "!room2" }] as unknown as Room[]);
|
||||
jest.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
|
||||
vi.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
|
||||
|
||||
// The device is verified
|
||||
mockCrypto.getDeviceVerificationStatus.mockResolvedValue(
|
||||
@@ -839,7 +843,7 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
|
||||
it("hides toast when reminder is snoozed", async () => {
|
||||
mocked(isBulkUnverifiedDeviceReminderSnoozed).mockReturnValue(true);
|
||||
vi.mocked(isBulkUnverifiedDeviceReminderSnoozed).mockReturnValue(true);
|
||||
// currentDevice, device2 are verified, device3 is unverified
|
||||
mockCrypto!.getDeviceVerificationStatus.mockImplementation(async (_userId, deviceId) => {
|
||||
switch (deviceId) {
|
||||
@@ -931,12 +935,12 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
|
||||
describe("Report verification and recovery state to Analytics", () => {
|
||||
let setPropertySpy: jest.SpyInstance;
|
||||
let trackEventSpy: jest.SpyInstance;
|
||||
let setPropertySpy: Mocked<PosthogAnalytics["setProperty"]>;
|
||||
let trackEventSpy: Mocked<PosthogAnalytics["trackEvent"]>;
|
||||
|
||||
beforeEach(() => {
|
||||
setPropertySpy = jest.spyOn(PosthogAnalytics.instance, "setProperty");
|
||||
trackEventSpy = jest.spyOn(PosthogAnalytics.instance, "trackEvent");
|
||||
setPropertySpy = vi.spyOn(PosthogAnalytics.instance, "setProperty");
|
||||
trackEventSpy = vi.spyOn(PosthogAnalytics.instance, "trackEvent");
|
||||
});
|
||||
|
||||
describe("Report crypto verification state to analytics", () => {
|
||||
@@ -1301,7 +1305,7 @@ describe("DeviceListener", () => {
|
||||
mockCrypto!.isCrossSigningReady.mockResolvedValue(true);
|
||||
mockCrypto!.getSecretStorageStatus.mockResolvedValue(unreadySecretStorageStatus);
|
||||
mockClient!.getRooms.mockReturnValue(rooms);
|
||||
jest.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
|
||||
vi.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(true);
|
||||
});
|
||||
|
||||
it("shows the 'set up recovery' toast if user has not set up 4S", async () => {
|
||||
@@ -1320,7 +1324,7 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
|
||||
it("does not show the 'set up recovery' toast if user has no encrypted rooms", async () => {
|
||||
jest.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(false);
|
||||
vi.spyOn(mockClient.getCrypto()!, "isEncryptionEnabledInRoom").mockResolvedValue(false);
|
||||
await createAndStart();
|
||||
|
||||
expect(SetupEncryptionToast.showToast).not.toHaveBeenCalledWith("set_up_recovery");
|
||||
+7
-6
@@ -6,12 +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 { vi, describe, it, expect, beforeEach } from "vitest";
|
||||
import React from "react";
|
||||
|
||||
import { formatList, formatCount, formatCountLong } from "../../../src/utils/FormattingUtils";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
import { formatList, formatCount, formatCountLong } from "./FormattingUtils";
|
||||
import SettingsStore from "../settings/SettingsStore";
|
||||
|
||||
jest.mock("../../../src/dispatcher/dispatcher");
|
||||
vi.mock("../dispatcher/dispatcher");
|
||||
|
||||
describe("FormattingUtils", () => {
|
||||
describe("formatCount", () => {
|
||||
@@ -37,8 +38,8 @@ describe("FormattingUtils", () => {
|
||||
|
||||
describe("formatList", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue("en-GB");
|
||||
vi.resetAllMocks();
|
||||
vi.spyOn(SettingsStore, "getValue").mockReturnValue("en-GB");
|
||||
});
|
||||
|
||||
it("should return empty string when given empty list", () => {
|
||||
@@ -54,7 +55,7 @@ describe("FormattingUtils", () => {
|
||||
});
|
||||
|
||||
it("should return expected sentence in German without item limit", () => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue("de");
|
||||
vi.spyOn(SettingsStore, "getValue").mockReturnValue("de");
|
||||
expect(formatList(["abc", "def", "ghi"])).toEqual("abc, def und ghi");
|
||||
});
|
||||
|
||||
+5
-2
@@ -6,11 +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 { render } from "jest-matrix-react";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { render } from "test-utils-rtl";
|
||||
|
||||
import type { IContent } from "matrix-js-sdk/src/matrix";
|
||||
import type React from "react";
|
||||
import { editBodyDiffToHtml } from "../../../src/utils/MessageDiffUtils";
|
||||
import { editBodyDiffToHtml } from "./MessageDiffUtils";
|
||||
|
||||
describe("editBodyDiffToHtml", () => {
|
||||
function buildContent(message: string): IContent {
|
||||
+4
-4
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`FormattingUtils formatList should return expected sentence in ReactNode when given 2 React children 1`] = `
|
||||
exports[`FormattingUtils > formatList > should return expected sentence in ReactNode when given 2 React children 1`] = `
|
||||
<React.Fragment>
|
||||
<React.Fragment>
|
||||
<span>
|
||||
@@ -18,7 +18,7 @@ exports[`FormattingUtils formatList should return expected sentence in ReactNode
|
||||
</React.Fragment>
|
||||
`;
|
||||
|
||||
exports[`FormattingUtils formatList should return expected sentence in ReactNode when given more React children 1`] = `
|
||||
exports[`FormattingUtils > formatList > should return expected sentence in ReactNode when given more React children 1`] = `
|
||||
<React.Fragment>
|
||||
<React.Fragment>
|
||||
<span>
|
||||
@@ -52,7 +52,7 @@ exports[`FormattingUtils formatList should return expected sentence in ReactNode
|
||||
</React.Fragment>
|
||||
`;
|
||||
|
||||
exports[`FormattingUtils formatList should return expected sentence in ReactNode when using itemLimit 1`] = `
|
||||
exports[`FormattingUtils > formatList > should return expected sentence in ReactNode when using itemLimit 1`] = `
|
||||
<span>
|
||||
<React.Fragment>
|
||||
<React.Fragment>
|
||||
+17
-17
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`editBodyDiffToHtml deduplicates diff steps 1`] = `
|
||||
exports[`editBodyDiffToHtml > deduplicates diff steps 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -28,7 +28,7 @@ exports[`editBodyDiffToHtml deduplicates diff steps 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml handles complex transformations 1`] = `
|
||||
exports[`editBodyDiffToHtml > handles complex transformations 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -76,7 +76,7 @@ exports[`editBodyDiffToHtml handles complex transformations 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml handles non-html input 1`] = `
|
||||
exports[`editBodyDiffToHtml > handles non-html input 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -95,7 +95,7 @@ exports[`editBodyDiffToHtml handles non-html input 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders attribute additions 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders attribute additions 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -159,7 +159,7 @@ exports[`editBodyDiffToHtml renders attribute additions 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders attribute deletions 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders attribute deletions 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -225,7 +225,7 @@ exports[`editBodyDiffToHtml renders attribute deletions 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders attribute modifications 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders attribute modifications 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -259,7 +259,7 @@ exports[`editBodyDiffToHtml renders attribute modifications 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders block element additions 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders block element additions 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -284,7 +284,7 @@ exports[`editBodyDiffToHtml renders block element additions 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders block element deletions 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders block element deletions 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -309,7 +309,7 @@ exports[`editBodyDiffToHtml renders block element deletions 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders central word changes 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders central word changes 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -340,7 +340,7 @@ exports[`editBodyDiffToHtml renders central word changes 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders element replacements 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders element replacements 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -367,7 +367,7 @@ exports[`editBodyDiffToHtml renders element replacements 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders handles empty tags 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders handles empty tags 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -398,7 +398,7 @@ exports[`editBodyDiffToHtml renders handles empty tags 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders inline element additions 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders inline element additions 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -416,7 +416,7 @@ exports[`editBodyDiffToHtml renders inline element additions 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders inline element deletions 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders inline element deletions 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -441,7 +441,7 @@ exports[`editBodyDiffToHtml renders inline element deletions 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders simple word changes 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders simple word changes 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -463,7 +463,7 @@ exports[`editBodyDiffToHtml renders simple word changes 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders text additions 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders text additions 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
@@ -481,7 +481,7 @@ exports[`editBodyDiffToHtml renders text additions 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`editBodyDiffToHtml renders text deletions 1`] = `
|
||||
exports[`editBodyDiffToHtml > renders text deletions 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_EventTile_body markdown-body"
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`createVoiceMessageContent should create a voice message content 1`] = `
|
||||
exports[`createVoiceMessageContent > should create a voice message content 1`] = `
|
||||
{
|
||||
"body": "Voice message",
|
||||
"file": {},
|
||||
+2
-1
@@ -6,9 +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.
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { type EncryptedFile } from "matrix-js-sdk/src/types";
|
||||
|
||||
import { createVoiceMessageContent } from "../../../src/utils/createVoiceMessageContent";
|
||||
import { createVoiceMessageContent } from "./createVoiceMessageContent";
|
||||
|
||||
describe("createVoiceMessageContent", () => {
|
||||
it("should create a voice message content", () => {
|
||||
+4
-2
@@ -6,8 +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.
|
||||
*/
|
||||
|
||||
import { PermalinkParts } from "../../../../src/utils/permalinks/PermalinkConstructor";
|
||||
import MatrixSchemePermalinkConstructor from "../../../../src/utils/permalinks/MatrixSchemePermalinkConstructor";
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import { PermalinkParts } from "./PermalinkConstructor";
|
||||
import MatrixSchemePermalinkConstructor from "./MatrixSchemePermalinkConstructor";
|
||||
|
||||
describe("MatrixSchemePermalinkConstructor", () => {
|
||||
const peramlinkConstructor = new MatrixSchemePermalinkConstructor();
|
||||
+4
-2
@@ -6,8 +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.
|
||||
*/
|
||||
|
||||
import MatrixToPermalinkConstructor from "../../../../src/utils/permalinks/MatrixToPermalinkConstructor";
|
||||
import { PermalinkParts } from "../../../../src/utils/permalinks/PermalinkConstructor";
|
||||
import { describe, it, expect } from "vitest";
|
||||
|
||||
import MatrixToPermalinkConstructor from "./MatrixToPermalinkConstructor";
|
||||
import { PermalinkParts } from "./PermalinkConstructor";
|
||||
|
||||
describe("MatrixToPermalinkConstructor", () => {
|
||||
const peramlinkConstructor = new MatrixToPermalinkConstructor();
|
||||
+16
-19
@@ -7,27 +7,24 @@ 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, describe, it, expect, afterAll, beforeEach } from "vitest";
|
||||
import { getMockClientWithEventEmitter } from "test-utils/client";
|
||||
|
||||
import { type EventEmitter } from "events";
|
||||
import { Room, RoomMember, EventType, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import { PermalinkParts } from "../../../../src/utils/permalinks/PermalinkConstructor";
|
||||
import {
|
||||
makeRoomPermalink,
|
||||
makeUserPermalink,
|
||||
parsePermalink,
|
||||
RoomPermalinkCreator,
|
||||
} from "../../../../src/utils/permalinks/Permalinks";
|
||||
import { type IConfigOptions } from "../../../../src/IConfigOptions";
|
||||
import SdkConfig from "../../../../src/SdkConfig";
|
||||
import { getMockClientWithEventEmitter } from "../../../test-utils";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
import { PermalinkParts } from "./PermalinkConstructor";
|
||||
import { makeRoomPermalink, makeUserPermalink, parsePermalink, RoomPermalinkCreator } from "./Permalinks";
|
||||
import { type IConfigOptions } from "../../IConfigOptions";
|
||||
import SdkConfig from "../../SdkConfig";
|
||||
|
||||
describe("Permalinks", function () {
|
||||
const userId = "@test:example.com";
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
getUserId: jest.fn().mockReturnValue(userId),
|
||||
getRoom: jest.fn(),
|
||||
getUserId: vi.fn().mockReturnValue(userId),
|
||||
getRoom: vi.fn(),
|
||||
});
|
||||
mockClient.credentials = { userId };
|
||||
|
||||
@@ -72,18 +69,18 @@ describe("Permalinks", function () {
|
||||
const stateEvents = serverACL ? [powerLevels, serverACL] : [powerLevels];
|
||||
room.currentState.setStateEvents(stateEvents);
|
||||
|
||||
jest.spyOn(room, "getCanonicalAlias").mockReturnValue(null);
|
||||
jest.spyOn(room, "getJoinedMembers").mockReturnValue(members);
|
||||
jest.spyOn(room, "getMember").mockImplementation((userId) => members.find((m) => m.userId === userId) || null);
|
||||
vi.spyOn(room, "getCanonicalAlias").mockReturnValue(null);
|
||||
vi.spyOn(room, "getJoinedMembers").mockReturnValue(members);
|
||||
vi.spyOn(room, "getMember").mockImplementation((userId) => members.find((m) => m.userId === userId) || null);
|
||||
|
||||
return room;
|
||||
}
|
||||
beforeEach(function () {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.spyOn(MatrixClientPeg, "get").mockRestore();
|
||||
vi.spyOn(MatrixClientPeg, "get").mockRestore();
|
||||
});
|
||||
|
||||
it("should not clean up listeners even if start was called multiple times", () => {
|
||||
@@ -416,7 +413,7 @@ describe("Permalinks", function () {
|
||||
|
||||
it("should use permalink_prefix for permalinks", function () {
|
||||
const sdkConfigGet = SdkConfig.get;
|
||||
jest.spyOn(SdkConfig, "get").mockImplementation((key: keyof IConfigOptions, altCaseName?: string) => {
|
||||
vi.spyOn(SdkConfig, "get").mockImplementation((key: keyof IConfigOptions, altCaseName?: string) => {
|
||||
if (key === "permalink_prefix") {
|
||||
return "https://element.fs.tld";
|
||||
} else return sdkConfigGet(key, altCaseName);
|
||||
+8
-6
@@ -6,12 +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 { type Mocked } from "jest-mock";
|
||||
import { type IIdentityServerProvider, type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { DirectoryMember, ThreepidMember } from "../../../src/utils/direct-messages";
|
||||
import { lookupThreePids, resolveThreePids } from "../../../src/utils/threepids";
|
||||
import { stubClient } from "../../test-utils";
|
||||
import { vi, describe, it, expect, beforeEach, type Mocked } from "vitest";
|
||||
import { type IIdentityServerProvider, type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { stubClient } from "test-utils";
|
||||
|
||||
import { DirectoryMember, ThreepidMember } from "./direct-messages";
|
||||
import { lookupThreePids, resolveThreePids } from "./threepids";
|
||||
|
||||
describe("threepids", () => {
|
||||
let client: Mocked<MatrixClient>;
|
||||
@@ -21,7 +23,7 @@ describe("threepids", () => {
|
||||
beforeEach(() => {
|
||||
client = stubClient() as Mocked<MatrixClient>;
|
||||
identityServer = {
|
||||
getAccessToken: jest.fn().mockResolvedValue(accessToken),
|
||||
getAccessToken: vi.fn().mockResolvedValue(accessToken),
|
||||
} as unknown as Mocked<IIdentityServerProvider>;
|
||||
});
|
||||
|
||||
+18
-13
@@ -5,8 +5,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 { vi, describe, it, expect, beforeEach } from "vitest";
|
||||
import { type MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked } from "jest-mock";
|
||||
import { stubClient } from "test-utils";
|
||||
|
||||
import {
|
||||
clearUserStatus,
|
||||
@@ -14,8 +17,7 @@ import {
|
||||
setUserStatus,
|
||||
userStatusFromProfile,
|
||||
userStatusTextWithinMaxLength,
|
||||
} from "../../../src/utils/userStatus";
|
||||
import { stubClient } from "../../test-utils";
|
||||
} from "./userStatus";
|
||||
|
||||
describe("userStatus utils", () => {
|
||||
describe("userStatusFromProfile", () => {
|
||||
@@ -88,19 +90,22 @@ describe("userStatus utils", () => {
|
||||
|
||||
beforeEach(() => {
|
||||
client = stubClient();
|
||||
client.doesServerSupportExtendedProfiles = jest.fn();
|
||||
client.doesServerSupportExtendedProfiles = vi.fn();
|
||||
});
|
||||
|
||||
it("returns undefined if the server does not support extended profiles", async () => {
|
||||
mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(false);
|
||||
vi.mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(false);
|
||||
|
||||
await expect(fetchUserStatus(client, "@alice:example.com")).resolves.toBeUndefined();
|
||||
expect(client.getExtendedProfileProperty).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns the validated status if the server supports extended profiles and has a status set", async () => {
|
||||
mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(true);
|
||||
mocked(client.getExtendedProfileProperty).mockResolvedValue({ emoji: "🐳", text: "Feeling a little blue" });
|
||||
vi.mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(true);
|
||||
vi.mocked(client.getExtendedProfileProperty).mockResolvedValue({
|
||||
emoji: "🐳",
|
||||
text: "Feeling a little blue",
|
||||
});
|
||||
|
||||
await expect(fetchUserStatus(client, "@alice:example.com")).resolves.toEqual({
|
||||
emoji: "🐳",
|
||||
@@ -113,15 +118,15 @@ describe("userStatus utils", () => {
|
||||
});
|
||||
|
||||
it("returns undefined if the status is invalid", async () => {
|
||||
mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(true);
|
||||
mocked(client.getExtendedProfileProperty).mockResolvedValue({ text: "Feeling a little blue" });
|
||||
vi.mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(true);
|
||||
vi.mocked(client.getExtendedProfileProperty).mockResolvedValue({ text: "Feeling a little blue" });
|
||||
|
||||
await expect(fetchUserStatus(client, "@alice:example.com")).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns undefined if the user has no status set", async () => {
|
||||
mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(true);
|
||||
mocked(client.getExtendedProfileProperty).mockRejectedValue(
|
||||
vi.mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(true);
|
||||
vi.mocked(client.getExtendedProfileProperty).mockRejectedValue(
|
||||
new MatrixError({ errcode: "M_NOT_FOUND" }, 404),
|
||||
);
|
||||
|
||||
@@ -129,9 +134,9 @@ describe("userStatus utils", () => {
|
||||
});
|
||||
|
||||
it("returns undefined and logs a warning if fetching the status fails unexpectedly", async () => {
|
||||
mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(true);
|
||||
vi.mocked(client.doesServerSupportExtendedProfiles).mockResolvedValue(true);
|
||||
const error = new Error("network error");
|
||||
mocked(client.getExtendedProfileProperty).mockRejectedValue(error);
|
||||
vi.mocked(client.getExtendedProfileProperty).mockRejectedValue(error);
|
||||
|
||||
await expect(fetchUserStatus(client, "@alice:example.com")).resolves.toBeUndefined();
|
||||
});
|
||||
+13
-11
@@ -5,13 +5,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import type { Mocked } from "jest-mock";
|
||||
import type { ConsoleLogger } from "../../../src/rageshake/rageshake";
|
||||
import SdkConfig from "../../../src/SdkConfig";
|
||||
import "../../../src/vector/rageshakesetup";
|
||||
import { BugReportEndpointURLLocal } from "../../../src/IConfigOptions";
|
||||
import { vi, describe, it, expect, beforeEach, afterEach, type Mocked } from "vitest";
|
||||
import fetchMock from "@fetch-mock/vitest";
|
||||
|
||||
import type { ConsoleLogger } from "../rageshake/rageshake";
|
||||
import SdkConfig from "../SdkConfig";
|
||||
import "./rageshakesetup";
|
||||
import { BugReportEndpointURLLocal } from "../IConfigOptions";
|
||||
|
||||
const RAGESHAKE_URL = "https://logs.example.org/logtome";
|
||||
|
||||
@@ -23,9 +25,9 @@ describe("mxSendRageshake", () => {
|
||||
fetchMock.postOnce(RAGESHAKE_URL, { status: 200, body: {} });
|
||||
|
||||
const mockConsoleLogger = {
|
||||
flush: jest.fn(),
|
||||
consume: jest.fn(),
|
||||
warn: jest.fn(),
|
||||
flush: vi.fn(),
|
||||
consume: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
} as unknown as Mocked<ConsoleLogger>;
|
||||
prevLogger = global.mx_rage_logger;
|
||||
mockConsoleLogger.flush.mockReturnValue("line 1\nline 2\n");
|
||||
@@ -34,7 +36,7 @@ describe("mxSendRageshake", () => {
|
||||
|
||||
afterEach(() => {
|
||||
global.mx_rage_logger = prevLogger;
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
fetchMock.unmockGlobal();
|
||||
SdkConfig.reset();
|
||||
});
|
||||
@@ -57,7 +59,7 @@ describe("mxSendRageshake", () => {
|
||||
|
||||
it("Provides a rageshake locally", async () => {
|
||||
SdkConfig.put({ bug_report_endpoint_url: BugReportEndpointURLLocal });
|
||||
const urlSpy = jest.spyOn(URL, "createObjectURL");
|
||||
const urlSpy = vi.spyOn(URL, "createObjectURL");
|
||||
await window.mxSendRageshake("Hello world");
|
||||
expect(fetchMock).not.toHaveFetched(RAGESHAKE_URL);
|
||||
expect(urlSpy).toHaveBeenCalledTimes(1);
|
||||
+39
-37
@@ -5,27 +5,28 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { vi, describe, it, expect, beforeEach, afterEach } from "vitest";
|
||||
import React from "react";
|
||||
import { mocked } from "jest-mock";
|
||||
import { ConnectionError, Direction } from "matrix-js-sdk/src/matrix";
|
||||
import { flushPromisesWithFakeTimers } from "test-utils/utilities";
|
||||
|
||||
import dispatcher from "../../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../../src/dispatcher/actions";
|
||||
import { formatFullDateNoTime } from "../../../src/DateUtils";
|
||||
import Modal from "../../../src/Modal";
|
||||
import { MatrixClientPeg } from "../../../src/MatrixClientPeg";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
import { UIFeature } from "../../../src/settings/UIFeature";
|
||||
import { SDKContextClass } from "../../../src/contexts/SDKContextClass";
|
||||
import { DateSeparatorViewModel } from "../../../src/viewmodels/room/timeline/DateSeparatorViewModel";
|
||||
import { flushPromisesWithFakeTimers } from "../../test-utils/utilities";
|
||||
import dispatcher from "../../../dispatcher/dispatcher";
|
||||
import { Action } from "../../../dispatcher/actions";
|
||||
import { formatFullDateNoTime } from "../../../DateUtils";
|
||||
import Modal from "../../../Modal";
|
||||
import { MatrixClientPeg } from "../../../MatrixClientPeg";
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import { UIFeature } from "../../../settings/UIFeature";
|
||||
import { SDKContextClass } from "../../../contexts/SDKContextClass";
|
||||
import { DateSeparatorViewModel } from "./DateSeparatorViewModel";
|
||||
|
||||
jest.mock("../../../src/settings/SettingsStore");
|
||||
jest.mock("../../../src/contexts/SDKContextClass", () => ({
|
||||
vi.mock("../../../Modal");
|
||||
vi.mock("../../../settings/SettingsStore");
|
||||
vi.mock("../../../contexts/SDKContextClass", () => ({
|
||||
SDKContextClass: {
|
||||
instance: {
|
||||
roomViewStore: {
|
||||
getRoomId: jest.fn(),
|
||||
getRoomId: vi.fn(),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -56,7 +57,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
];
|
||||
|
||||
const watchCallbacks = new Map<string, (...args: any[]) => void>();
|
||||
const mockTimestampToEvent = jest.fn();
|
||||
const mockTimestampToEvent = vi.fn();
|
||||
|
||||
const hasTestId = (node: React.ReactNode, testId: string): boolean => {
|
||||
if (!React.isValidElement<{ children?: React.ReactNode }>(node)) return false;
|
||||
@@ -78,35 +79,36 @@ describe("DateSeparatorViewModel", () => {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
jest.setSystemTime(nowDate.getTime());
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(nowDate.getTime());
|
||||
watchCallbacks.clear();
|
||||
|
||||
mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
vi.mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
if (String(key) === UIFeature.TimelineEnableRelativeDates) return true;
|
||||
if (key === "feature_jump_to_date") return false;
|
||||
return undefined;
|
||||
});
|
||||
mocked(SettingsStore).watchSetting.mockImplementation((settingName, _roomId, cb): any => {
|
||||
vi.mocked(SettingsStore).watchSetting.mockImplementation((settingName, _roomId, cb): any => {
|
||||
watchCallbacks.set(String(settingName), cb);
|
||||
return `${String(settingName)}-watch-ref`;
|
||||
});
|
||||
mocked(SettingsStore).unwatchSetting.mockImplementation(() => {});
|
||||
vi.mocked(SettingsStore).unwatchSetting.mockImplementation(() => {});
|
||||
|
||||
mockTimestampToEvent.mockReset();
|
||||
jest.spyOn(MatrixClientPeg, "safeGet").mockReturnValue({
|
||||
vi.spyOn(MatrixClientPeg, "safeGet").mockReturnValue({
|
||||
timestampToEvent: mockTimestampToEvent,
|
||||
} as any);
|
||||
|
||||
jest.spyOn(dispatcher, "dispatch").mockImplementation(() => {});
|
||||
jest.spyOn(Modal, "createDialog").mockImplementation(() => ({ close: jest.fn() }) as any);
|
||||
vi.spyOn(dispatcher, "dispatch").mockImplementation(() => {});
|
||||
vi.spyOn(Modal, "createDialog").mockImplementation(() => ({ close: vi.fn() }) as any);
|
||||
|
||||
mocked(SDKContextClass.instance.roomViewStore.getRoomId).mockReturnValue(roomId);
|
||||
vi.mocked(SDKContextClass.instance.roomViewStore.getRoomId).mockReturnValue(roomId);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
jest.useRealTimers();
|
||||
vi.restoreAllMocks();
|
||||
vi.clearAllMocks();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("computes relative label for today", () => {
|
||||
@@ -133,7 +135,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
});
|
||||
|
||||
it("exposes jumpToDateMenu when feature is enabled", () => {
|
||||
mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
vi.mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
if (String(key) === UIFeature.TimelineEnableRelativeDates) return true;
|
||||
if (key === "feature_jump_to_date") return true;
|
||||
return undefined;
|
||||
@@ -150,7 +152,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
});
|
||||
|
||||
it("does not expose jumpToDateMenu when exporting", () => {
|
||||
mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
vi.mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
if (String(key) === UIFeature.TimelineEnableRelativeDates) return true;
|
||||
if (key === "feature_jump_to_date") return true;
|
||||
return undefined;
|
||||
@@ -197,7 +199,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
event_id: "$event",
|
||||
origin_server_ts: nowDate.getTime(),
|
||||
});
|
||||
mocked(SDKContextClass.instance.roomViewStore.getRoomId).mockReturnValue("!other:example.org");
|
||||
vi.mocked(SDKContextClass.instance.roomViewStore.getRoomId).mockReturnValue("!other:example.org");
|
||||
const vm = createViewModel();
|
||||
|
||||
await vm.pickDate(nowDate.getTime() - HOUR_MS);
|
||||
@@ -212,7 +214,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
await vm.pickDate(nowDate.getTime() - HOUR_MS);
|
||||
|
||||
expect(Modal.createDialog).toHaveBeenCalled();
|
||||
const [, params] = mocked(Modal.createDialog).mock.calls.at(-1)!;
|
||||
const [, params] = vi.mocked(Modal.createDialog).mock.calls.at(-1)!;
|
||||
expect(hasTestId((params as any).description, "jump-to-date-error-submit-debug-logs-button")).toBe(true);
|
||||
});
|
||||
|
||||
@@ -223,7 +225,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
await vm.pickDate(nowDate.getTime() - HOUR_MS);
|
||||
|
||||
expect(Modal.createDialog).toHaveBeenCalled();
|
||||
const [, params] = mocked(Modal.createDialog).mock.calls.at(-1)!;
|
||||
const [, params] = vi.mocked(Modal.createDialog).mock.calls.at(-1)!;
|
||||
expect(hasTestId((params as any).description, "jump-to-date-error-submit-debug-logs-button")).toBe(false);
|
||||
});
|
||||
|
||||
@@ -242,7 +244,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
|
||||
describe("when TimelineEnableRelativeDates is false", () => {
|
||||
beforeEach(() => {
|
||||
mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
vi.mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
if (String(key) === UIFeature.TimelineEnableRelativeDates) return false;
|
||||
if (key === "feature_jump_to_date") return false;
|
||||
return undefined;
|
||||
@@ -257,7 +259,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
|
||||
describe("jump actions", () => {
|
||||
beforeEach(() => {
|
||||
mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
vi.mocked(SettingsStore).getValue.mockImplementation((key): any => {
|
||||
if (String(key) === UIFeature.TimelineEnableRelativeDates) return true;
|
||||
if (key === "feature_jump_to_date") return true;
|
||||
return undefined;
|
||||
@@ -303,7 +305,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
});
|
||||
|
||||
it("does not jump when room changed before request resolves", async () => {
|
||||
mocked(SDKContextClass.instance.roomViewStore.getRoomId).mockReturnValue("!some-other-room");
|
||||
vi.mocked(SDKContextClass.instance.roomViewStore.getRoomId).mockReturnValue("!some-other-room");
|
||||
mockTimestampToEvent.mockResolvedValue({
|
||||
event_id: "$abc",
|
||||
origin_server_ts: 0,
|
||||
@@ -317,7 +319,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
});
|
||||
|
||||
it("does not show jump to date error if user switched room", async () => {
|
||||
mocked(SDKContextClass.instance.roomViewStore.getRoomId).mockReturnValue("!some-other-room");
|
||||
vi.mocked(SDKContextClass.instance.roomViewStore.getRoomId).mockReturnValue("!some-other-room");
|
||||
mockTimestampToEvent.mockRejectedValue(new Error("Fake error in test"));
|
||||
const vm = createViewModel();
|
||||
|
||||
@@ -335,7 +337,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
await flushPromisesWithFakeTimers();
|
||||
|
||||
expect(Modal.createDialog).toHaveBeenCalled();
|
||||
const [, params] = mocked(Modal.createDialog).mock.calls.at(-1)!;
|
||||
const [, params] = vi.mocked(Modal.createDialog).mock.calls.at(-1)!;
|
||||
expect(hasTestId((params as any).description, "jump-to-date-error-submit-debug-logs-button")).toBe(true);
|
||||
});
|
||||
|
||||
@@ -347,7 +349,7 @@ describe("DateSeparatorViewModel", () => {
|
||||
await flushPromisesWithFakeTimers();
|
||||
|
||||
expect(Modal.createDialog).toHaveBeenCalled();
|
||||
const [, params] = mocked(Modal.createDialog).mock.calls.at(-1)!;
|
||||
const [, params] = vi.mocked(Modal.createDialog).mock.calls.at(-1)!;
|
||||
expect(hasTestId((params as any).description, "jump-to-date-error-submit-debug-logs-button")).toBe(false);
|
||||
});
|
||||
});
|
||||
+10
-8
@@ -5,7 +5,9 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { DisambiguatedProfileViewModel } from "../../../src/viewmodels/room/timeline/event-tile/DisambiguatedProfileViewModel";
|
||||
import { vi, describe, it, expect } from "vitest";
|
||||
|
||||
import { DisambiguatedProfileViewModel } from "./DisambiguatedProfileViewModel";
|
||||
|
||||
describe("DisambiguatedProfileViewModel", () => {
|
||||
const member = {
|
||||
@@ -53,14 +55,14 @@ describe("DisambiguatedProfileViewModel", () => {
|
||||
});
|
||||
|
||||
it("should delegate onClick without emitting a snapshot update", () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const vm = new DisambiguatedProfileViewModel({
|
||||
member,
|
||||
fallbackName: "Fallback",
|
||||
onClick,
|
||||
});
|
||||
const prevSnapshot = vm.getSnapshot();
|
||||
const subscriber = jest.fn();
|
||||
const subscriber = vi.fn();
|
||||
|
||||
vm.subscribe(subscriber);
|
||||
vm.onClick?.({} as never);
|
||||
@@ -71,7 +73,7 @@ describe("DisambiguatedProfileViewModel", () => {
|
||||
});
|
||||
|
||||
it("should keep onClick bound when extracted as a callback", () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const vm = new DisambiguatedProfileViewModel({
|
||||
member,
|
||||
fallbackName: "Fallback",
|
||||
@@ -89,7 +91,7 @@ describe("DisambiguatedProfileViewModel", () => {
|
||||
member: null,
|
||||
fallbackName: "Fallback",
|
||||
});
|
||||
const subscriber = jest.fn();
|
||||
const subscriber = vi.fn();
|
||||
|
||||
vm.subscribe(subscriber);
|
||||
vm.setMember("Updated");
|
||||
@@ -103,7 +105,7 @@ describe("DisambiguatedProfileViewModel", () => {
|
||||
member: null,
|
||||
fallbackName: "Fallback",
|
||||
});
|
||||
const subscriber = jest.fn();
|
||||
const subscriber = vi.fn();
|
||||
|
||||
vm.subscribe(subscriber);
|
||||
vm.setMember("Fallback");
|
||||
@@ -136,7 +138,7 @@ describe("DisambiguatedProfileViewModel", () => {
|
||||
member: null,
|
||||
fallbackName: "Fallback",
|
||||
});
|
||||
const subscriber = jest.fn();
|
||||
const subscriber = vi.fn();
|
||||
|
||||
vm.subscribe(subscriber);
|
||||
vm.setMember("Fallback", member);
|
||||
@@ -150,7 +152,7 @@ describe("DisambiguatedProfileViewModel", () => {
|
||||
member,
|
||||
fallbackName: "Fallback",
|
||||
});
|
||||
const subscriber = jest.fn();
|
||||
const subscriber = vi.fn();
|
||||
|
||||
vm.subscribe(subscriber);
|
||||
vm.setMember("Fallback", member);
|
||||
+9
-5
@@ -5,12 +5,16 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, beforeEach } from "vitest";
|
||||
|
||||
import { type ChangeEvent, type KeyboardEvent as ReactKeyboardEvent } from "react";
|
||||
import { waitFor } from "@testing-library/dom";
|
||||
|
||||
import { type Playback, PlaybackState } from "../../../src/audio/Playback";
|
||||
import { AudioPlayerViewModel } from "../../../src/viewmodels/room/timeline/event-tile/body/AudioPlayerViewModel";
|
||||
import { MockedPlayback } from "../../unit-tests/audio/MockedPlayback";
|
||||
import { type Playback, PlaybackState } from "../../../../../audio/Playback";
|
||||
import { AudioPlayerViewModel } from "./AudioPlayerViewModel";
|
||||
import { MockedPlayback } from "../../../../../../test/unit-tests/audio/MockedPlayback";
|
||||
|
||||
describe("AudioPlayerViewModel", () => {
|
||||
let playback: Playback;
|
||||
@@ -45,7 +49,7 @@ describe("AudioPlayerViewModel", () => {
|
||||
});
|
||||
|
||||
it("should has error=true when playback.prepare fails", async () => {
|
||||
jest.spyOn(playback, "prepare").mockRejectedValue(new Error("Failed to prepare playback"));
|
||||
vi.spyOn(playback, "prepare").mockRejectedValue(new Error("Failed to prepare playback"));
|
||||
const vm = new AudioPlayerViewModel({ playback, mediaName: "mediaName" });
|
||||
await waitFor(() => expect(vm.getSnapshot().error).toBe(true));
|
||||
});
|
||||
@@ -68,7 +72,7 @@ describe("AudioPlayerViewModel", () => {
|
||||
it("does not stop propagation for unhandled key down events", () => {
|
||||
const vm = new AudioPlayerViewModel({ playback, mediaName: "mediaName" });
|
||||
const event = new KeyboardEvent("keydown", { key: "a" });
|
||||
const stopPropagationSpy = jest.spyOn(event, "stopPropagation");
|
||||
const stopPropagationSpy = vi.spyOn(event, "stopPropagation");
|
||||
|
||||
vm.onKeyDown(event as unknown as ReactKeyboardEvent<HTMLDivElement>);
|
||||
|
||||
+19
-14
@@ -5,17 +5,22 @@
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { waitFor } from "jest-matrix-react";
|
||||
// @vitest-environment happy-dom
|
||||
|
||||
import { vi, describe, it, expect, afterEach } from "vitest";
|
||||
|
||||
import { waitFor } from "test-utils-rtl";
|
||||
import { type PanelImperativeHandle } from "@element-hq/web-shared-components";
|
||||
|
||||
import { ResizerViewModel } from "../../../src/viewmodels/structures/ResizerViewModel";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||||
import { ResizerViewModel } from "./ResizerViewModel";
|
||||
import SettingsStore from "../../settings/SettingsStore";
|
||||
import { SettingLevel } from "../../settings/SettingLevel";
|
||||
|
||||
jest.mock("what-input");
|
||||
vi.mock("what-input");
|
||||
|
||||
describe("LeftPanelResizerViewModel", () => {
|
||||
afterEach(() => {
|
||||
localStorage.clear();
|
||||
SettingsStore.reset();
|
||||
});
|
||||
|
||||
@@ -72,8 +77,8 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
SettingsStore.setValue("RoomList.panelSize", null, SettingLevel.DEVICE, 34);
|
||||
const mockHandle = {
|
||||
resize: jest.fn(),
|
||||
isCollapsed: jest.fn().mockReturnValue(true),
|
||||
resize: vi.fn(),
|
||||
isCollapsed: vi.fn().mockReturnValue(true),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
@@ -90,8 +95,8 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
SettingsStore.setValue("RoomList.panelSize", null, SettingLevel.DEVICE, 34);
|
||||
const mockHandle = {
|
||||
resize: jest.fn(),
|
||||
isCollapsed: jest.fn().mockReturnValue(true),
|
||||
resize: vi.fn(),
|
||||
isCollapsed: vi.fn().mockReturnValue(true),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
// Simulate click
|
||||
@@ -103,8 +108,8 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
it("to maximum size of the panel", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
const mockHandle = {
|
||||
resize: jest.fn(),
|
||||
isCollapsed: jest.fn().mockReturnValue(true),
|
||||
resize: vi.fn(),
|
||||
isCollapsed: vi.fn().mockReturnValue(true),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
// Simulate click
|
||||
@@ -117,8 +122,8 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
it("should collapse panel on click when panel is expanded", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
const mockHandle = {
|
||||
collapse: jest.fn(),
|
||||
isCollapsed: jest.fn().mockReturnValue(false),
|
||||
collapse: vi.fn(),
|
||||
isCollapsed: vi.fn().mockReturnValue(false),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
@@ -129,7 +134,7 @@ describe("LeftPanelResizerViewModel", () => {
|
||||
it("should resize to nearest whole number", () => {
|
||||
const vm = new ResizerViewModel();
|
||||
const mockHandle = {
|
||||
resize: jest.fn(),
|
||||
resize: vi.fn(),
|
||||
} as unknown as PanelImperativeHandle;
|
||||
vm.setPanelHandle(mockHandle);
|
||||
|
||||
@@ -9,6 +9,7 @@ import EventEmitter from "events";
|
||||
import { SimpleObservable } from "matrix-widget-api";
|
||||
|
||||
import { PlaybackState } from "../../../src/audio/Playback";
|
||||
import { vi } from "../../setup/adapter.ts";
|
||||
|
||||
/**
|
||||
* A mocked playback implementation for testing purposes.
|
||||
@@ -51,8 +52,8 @@ export class MockedPlayback extends EventEmitter {
|
||||
return this.waveformObservable;
|
||||
}
|
||||
|
||||
public prepare = jest.fn().mockResolvedValue(undefined);
|
||||
public skipTo = jest.fn();
|
||||
public toggle = jest.fn();
|
||||
public destroy = jest.fn().mockResolvedValue(undefined);
|
||||
public prepare = vi.fn().mockResolvedValue(undefined);
|
||||
public skipTo = vi.fn();
|
||||
public toggle = vi.fn();
|
||||
public destroy = vi.fn().mockResolvedValue(undefined);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user