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