Migrate more jest tests to vitest (#33898)
* Migrate more jest tests to vitest * Fix jest config * Fix jest config * Make remaining jest tests type-happy
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2026 Element Creations Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { vi } from "vitest";
|
||||
import { mocked as jestMocked } from "jest-mock";
|
||||
|
||||
const isJest = typeof jest !== "undefined";
|
||||
|
||||
/**
|
||||
* Subset of the vitest API surface, with jest equivalents for the same functions when running under jest.
|
||||
*/
|
||||
const adapter = {
|
||||
fn: isJest ? (jest.fn as unknown as typeof vi.fn) : vi.fn,
|
||||
spyOn: isJest ? (jest.spyOn as unknown as typeof vi.spyOn) : vi.spyOn,
|
||||
mocked: isJest ? (jestMocked as typeof vi.mocked) : vi.mocked,
|
||||
} as Pick<typeof vi, "fn" | "spyOn" | "mocked">;
|
||||
|
||||
const mocked = adapter.mocked;
|
||||
export { adapter as vi, mocked };
|
||||
|
||||
export { type Mocked, type MockedObject } from "vitest";
|
||||
@@ -6,23 +6,25 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { vi } from "./adapter.ts";
|
||||
|
||||
export const mocks = {
|
||||
AudioBufferSourceNode: {
|
||||
connect: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
connect: vi.fn(),
|
||||
start: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
} as unknown as AudioBufferSourceNode,
|
||||
AudioContext: {
|
||||
close: jest.fn(),
|
||||
createMediaElementSource: jest.fn(),
|
||||
createMediaStreamDestination: jest.fn(),
|
||||
createMediaStreamSource: jest.fn(),
|
||||
createStreamTrackSource: jest.fn(),
|
||||
createBufferSource: jest.fn((): AudioBufferSourceNode => ({ ...mocks.AudioBufferSourceNode })),
|
||||
getOutputTimestamp: jest.fn(),
|
||||
resume: jest.fn(),
|
||||
setSinkId: jest.fn(),
|
||||
suspend: jest.fn(),
|
||||
decodeAudioData: jest.fn(),
|
||||
close: vi.fn(),
|
||||
createMediaElementSource: vi.fn(),
|
||||
createMediaStreamDestination: vi.fn(),
|
||||
createMediaStreamSource: vi.fn(),
|
||||
createStreamTrackSource: vi.fn(),
|
||||
createBufferSource: vi.fn((): AudioBufferSourceNode => ({ ...mocks.AudioBufferSourceNode })),
|
||||
getOutputTimestamp: vi.fn(),
|
||||
resume: vi.fn(),
|
||||
setSinkId: vi.fn(),
|
||||
suspend: vi.fn(),
|
||||
decodeAudioData: vi.fn(),
|
||||
} as unknown as AudioContext,
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ import { env } from "process";
|
||||
import "@testing-library/jest-dom";
|
||||
import "blob-polyfill";
|
||||
import { secureRandomString } from "matrix-js-sdk/src/randomstring";
|
||||
import { mocked } from "jest-mock";
|
||||
import { mocked } from "jest-mock-vitest-adapter";
|
||||
|
||||
import { PredictableRandom } from "./test-utils/predictableRandom";
|
||||
import * as rageshake from "../src/rageshake/rageshake";
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type MockedObject } from "jest-mock";
|
||||
import { type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import {
|
||||
type MatrixClient,
|
||||
MatrixEvent,
|
||||
@@ -165,7 +165,7 @@ export const mockGeolocation = (): MockedObject<Geolocation> => {
|
||||
* See for error codes: https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError
|
||||
*/
|
||||
export const watchPositionMockImplementation = (delays: number[], errorCodes: number[] = []) => {
|
||||
return (callback: PositionCallback, error: PositionErrorCallback): number => {
|
||||
return (callback: PositionCallback, error?: PositionErrorCallback | null): number => {
|
||||
const position = makeGeolocationPosition({});
|
||||
|
||||
let totalDelay = 0;
|
||||
@@ -173,7 +173,7 @@ export const watchPositionMockImplementation = (delays: number[], errorCodes: nu
|
||||
totalDelay += delayMs;
|
||||
const timeout = window.setTimeout(() => {
|
||||
if (errorCodes[index]) {
|
||||
error(getMockGeolocationPositionError(errorCodes[index], "error message"));
|
||||
error?.(getMockGeolocationPositionError(errorCodes[index], "error message"));
|
||||
} else {
|
||||
callback({ ...position, timestamp: position.timestamp + totalDelay });
|
||||
}
|
||||
|
||||
@@ -7,11 +7,14 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import EventEmitter from "events";
|
||||
import { type MethodLikeKeys, mocked, type MockedObject, type PropertyLikeKeys } from "jest-mock";
|
||||
import { type MockedObject } from "vitest";
|
||||
import { type MethodLikeKeys, type PropertyLikeKeys } from "jest-mock";
|
||||
import { type MockedObjectDeep } from "@vitest/spy";
|
||||
import { Feature, ServerSupport } from "matrix-js-sdk/src/feature";
|
||||
import { type MatrixClient, type Room, User } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||
import { vi } from "../setup/adapter.ts";
|
||||
|
||||
/**
|
||||
* Mocked generic class with a real EventEmitter.
|
||||
@@ -53,7 +56,7 @@ export class MockClientWithEventEmitter extends EventEmitter {
|
||||
* eg
|
||||
* ```
|
||||
* const mockClient = getMockClientWithEventEmitter({
|
||||
getUserId: jest.fn().mockReturnValue(aliceId),
|
||||
getUserId: vi.fn().mockReturnValue(aliceId),
|
||||
});
|
||||
* ```
|
||||
*
|
||||
@@ -62,10 +65,10 @@ export class MockClientWithEventEmitter extends EventEmitter {
|
||||
export const getMockClientWithEventEmitter = (
|
||||
mockProperties: Partial<Record<keyof MatrixClient, unknown>>,
|
||||
): MockedObject<MatrixClient> => {
|
||||
const mock = mocked(new MockClientWithEventEmitter(mockProperties) as unknown as MatrixClient);
|
||||
const mock = vi.mocked(new MockClientWithEventEmitter(mockProperties) as unknown as MatrixClient);
|
||||
|
||||
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mock);
|
||||
jest.spyOn(MatrixClientPeg, "safeGet").mockReturnValue(mock);
|
||||
vi.spyOn(MatrixClientPeg, "get").mockReturnValue(mock);
|
||||
vi.spyOn(MatrixClientPeg, "safeGet").mockReturnValue(mock);
|
||||
|
||||
// @ts-ignore simplified test stub
|
||||
mock.canSupport = new Map();
|
||||
@@ -76,8 +79,8 @@ export const getMockClientWithEventEmitter = (
|
||||
};
|
||||
|
||||
export const unmockClientPeg = () => {
|
||||
jest.spyOn(MatrixClientPeg, "get").mockRestore();
|
||||
jest.spyOn(MatrixClientPeg, "safeGet").mockRestore();
|
||||
vi.spyOn(MatrixClientPeg, "get").mockRestore();
|
||||
vi.spyOn(MatrixClientPeg, "safeGet").mockRestore();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -88,19 +91,20 @@ export const unmockClientPeg = () => {
|
||||
});
|
||||
* ```
|
||||
*/
|
||||
export const mockClientMethodsUser = (userId = "@alice:domain") => ({
|
||||
getUserId: jest.fn().mockReturnValue(userId),
|
||||
getDomain: jest.fn().mockReturnValue(userId.split(":")[1]),
|
||||
getSafeUserId: jest.fn().mockReturnValue(userId),
|
||||
getUser: jest.fn().mockReturnValue(new User(userId)),
|
||||
isGuest: jest.fn().mockReturnValue(false),
|
||||
mxcUrlToHttp: jest.fn().mockReturnValue("mock-mxcUrlToHttp"),
|
||||
credentials: { userId },
|
||||
getThreePids: jest.fn().mockResolvedValue({ threepids: [] }),
|
||||
getAccessToken: jest.fn(),
|
||||
getDeviceId: jest.fn(),
|
||||
getAccountData: jest.fn(),
|
||||
});
|
||||
export const mockClientMethodsUser = (userId = "@alice:domain") =>
|
||||
({
|
||||
getUserId: vi.fn().mockReturnValue(userId),
|
||||
getDomain: vi.fn().mockReturnValue(userId.split(":")[1]),
|
||||
getSafeUserId: vi.fn().mockReturnValue(userId),
|
||||
getUser: vi.fn().mockReturnValue(new User(userId)),
|
||||
isGuest: vi.fn().mockReturnValue(false),
|
||||
mxcUrlToHttp: vi.fn().mockReturnValue("mock-mxcUrlToHttp"),
|
||||
credentials: { userId },
|
||||
getThreePids: vi.fn().mockResolvedValue({ threepids: [] }),
|
||||
getAccessToken: vi.fn(),
|
||||
getDeviceId: vi.fn(),
|
||||
getAccountData: vi.fn(),
|
||||
}) satisfies MockedObjectDeep<any>;
|
||||
|
||||
/**
|
||||
* Returns basic mocked client methods related to rendering events
|
||||
@@ -110,58 +114,60 @@ export const mockClientMethodsUser = (userId = "@alice:domain") => ({
|
||||
});
|
||||
* ```
|
||||
*/
|
||||
export const mockClientMethodsEvents = () => ({
|
||||
decryptEventIfNeeded: jest.fn(),
|
||||
getPushActionsForEvent: jest.fn(),
|
||||
});
|
||||
export const mockClientMethodsEvents = () =>
|
||||
({
|
||||
decryptEventIfNeeded: vi.fn(),
|
||||
getPushActionsForEvent: vi.fn(),
|
||||
}) satisfies MockedObjectDeep<any>;
|
||||
|
||||
/**
|
||||
* Returns basic mocked pushProcessor
|
||||
*/
|
||||
export const mockClientPushProcessor = () => ({
|
||||
pushProcessor: {
|
||||
getPushRuleById: jest.fn(),
|
||||
ruleMatchesEvent: jest.fn(),
|
||||
},
|
||||
});
|
||||
export const mockClientPushProcessor = () =>
|
||||
({
|
||||
pushProcessor: {
|
||||
getPushRuleById: vi.fn(),
|
||||
ruleMatchesEvent: vi.fn(),
|
||||
},
|
||||
}) satisfies MockedObjectDeep<any>;
|
||||
|
||||
/**
|
||||
* Returns basic mocked client methods related to server support
|
||||
*/
|
||||
export const mockClientMethodsServer = (): Partial<Record<MethodLikeKeys<MatrixClient>, unknown>> => ({
|
||||
getIdentityServerUrl: jest.fn(),
|
||||
getHomeserverUrl: jest.fn(),
|
||||
getCapabilities: jest.fn().mockResolvedValue({}),
|
||||
getCachedCapabilities: jest.fn().mockResolvedValue({}),
|
||||
getClientWellKnown: jest.fn().mockReturnValue({}),
|
||||
waitForClientWellKnown: jest.fn().mockResolvedValue({}),
|
||||
doesServerSupportUnstableFeature: jest.fn().mockResolvedValue(false),
|
||||
isVersionSupported: jest.fn().mockResolvedValue(false),
|
||||
getVersions: jest.fn().mockResolvedValue({}),
|
||||
isFallbackICEServerAllowed: jest.fn(),
|
||||
getIdentityServerUrl: vi.fn(),
|
||||
getHomeserverUrl: vi.fn(),
|
||||
getCapabilities: vi.fn().mockResolvedValue({}),
|
||||
getCachedCapabilities: vi.fn().mockResolvedValue({}),
|
||||
getClientWellKnown: vi.fn().mockReturnValue({}),
|
||||
waitForClientWellKnown: vi.fn().mockResolvedValue({}),
|
||||
doesServerSupportUnstableFeature: vi.fn().mockResolvedValue(false),
|
||||
isVersionSupported: vi.fn().mockResolvedValue(false),
|
||||
getVersions: vi.fn().mockResolvedValue({}),
|
||||
isFallbackICEServerAllowed: vi.fn(),
|
||||
});
|
||||
|
||||
export const mockClientMethodsDevice = (
|
||||
deviceId = "test-device-id",
|
||||
): Partial<Record<MethodLikeKeys<MatrixClient>, unknown>> => ({
|
||||
getDeviceId: jest.fn().mockReturnValue(deviceId),
|
||||
getDevices: jest.fn().mockResolvedValue({ devices: [] }),
|
||||
getDeviceId: vi.fn().mockReturnValue(deviceId),
|
||||
getDevices: vi.fn().mockResolvedValue({ devices: [] }),
|
||||
});
|
||||
|
||||
export const mockClientMethodsCrypto = (): Partial<
|
||||
Record<MethodLikeKeys<MatrixClient> & PropertyLikeKeys<MatrixClient>, unknown>
|
||||
> => ({
|
||||
isKeyBackupKeyStored: jest.fn(),
|
||||
getCrossSigningCacheCallbacks: jest.fn().mockReturnValue({ getCrossSigningKeyCache: jest.fn() }),
|
||||
isKeyBackupKeyStored: vi.fn(),
|
||||
getCrossSigningCacheCallbacks: vi.fn().mockReturnValue({ getCrossSigningKeyCache: vi.fn() }),
|
||||
secretStorage: {
|
||||
hasKey: jest.fn(),
|
||||
isStored: jest.fn().mockResolvedValue(null),
|
||||
getDefaultKeyId: jest.fn().mockResolvedValue(null),
|
||||
hasKey: vi.fn(),
|
||||
isStored: vi.fn().mockResolvedValue(null),
|
||||
getDefaultKeyId: vi.fn().mockResolvedValue(null),
|
||||
},
|
||||
getCrypto: jest.fn().mockReturnValue({
|
||||
getUserDeviceInfo: jest.fn(),
|
||||
getDeviceVerificationStatus: jest.fn().mockResolvedValue(null),
|
||||
getCrossSigningStatus: jest.fn().mockResolvedValue({
|
||||
getCrypto: vi.fn().mockReturnValue({
|
||||
getUserDeviceInfo: vi.fn(),
|
||||
getDeviceVerificationStatus: vi.fn().mockResolvedValue(null),
|
||||
getCrossSigningStatus: vi.fn().mockResolvedValue({
|
||||
publicKeysOnDevice: true,
|
||||
privateKeysInSecretStorage: false,
|
||||
privateKeysCachedLocally: {
|
||||
@@ -170,19 +176,19 @@ export const mockClientMethodsCrypto = (): Partial<
|
||||
userSigningKey: true,
|
||||
},
|
||||
}),
|
||||
isCrossSigningReady: jest.fn().mockResolvedValue(true),
|
||||
isSecretStorageReady: jest.fn(),
|
||||
getSessionBackupPrivateKey: jest.fn(),
|
||||
getVersion: jest.fn().mockReturnValue("Version 0"),
|
||||
getOwnDeviceKeys: jest.fn().mockReturnValue(new Promise(() => {})),
|
||||
getCrossSigningKeyId: jest.fn(),
|
||||
isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false),
|
||||
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
|
||||
isCrossSigningReady: vi.fn().mockResolvedValue(true),
|
||||
isSecretStorageReady: vi.fn(),
|
||||
getSessionBackupPrivateKey: vi.fn(),
|
||||
getVersion: vi.fn().mockReturnValue("Version 0"),
|
||||
getOwnDeviceKeys: vi.fn().mockReturnValue(new Promise(() => {})),
|
||||
getCrossSigningKeyId: vi.fn(),
|
||||
isEncryptionEnabledInRoom: vi.fn().mockResolvedValue(false),
|
||||
getKeyBackupInfo: vi.fn().mockResolvedValue(null),
|
||||
}),
|
||||
});
|
||||
|
||||
export const mockClientMethodsRooms = (rooms: Room[] = []): Partial<Record<MethodLikeKeys<MatrixClient>, unknown>> => ({
|
||||
getRooms: jest.fn().mockReturnValue(rooms),
|
||||
getRoom: jest.fn((roomId) => rooms.find((r) => r.roomId === roomId) ?? null),
|
||||
isRoomEncrypted: jest.fn(),
|
||||
getRooms: vi.fn().mockReturnValue(rooms),
|
||||
getRoom: vi.fn((roomId) => rooms.find((r) => r.roomId === roomId) ?? null),
|
||||
isRoomEncrypted: vi.fn(),
|
||||
});
|
||||
|
||||
@@ -6,19 +6,21 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { vi } from "../setup/adapter.ts";
|
||||
|
||||
export const REPEATABLE_DATE = new Date(2022, 10, 17, 16, 58, 32, 517);
|
||||
|
||||
const RealDateTimeFormat = global.Intl.DateTimeFormat;
|
||||
const RealDateTimeFormat = globalThis.Intl.DateTimeFormat;
|
||||
|
||||
// allow setting default locale and set timezone
|
||||
// defaults to en-GB / Europe/London
|
||||
// so tests run the same everywhere
|
||||
export const mockIntlDateTimeFormat = (defaultLocale = "en-GB", defaultTimezone = "Europe/London"): void => {
|
||||
jest.spyOn(global.Intl, "DateTimeFormat").mockImplementation(
|
||||
(locale, options) => new RealDateTimeFormat(locale || defaultLocale, { ...options, timeZone: defaultTimezone }),
|
||||
);
|
||||
vi.spyOn(globalThis.Intl, "DateTimeFormat").mockImplementation(function (locale, options) {
|
||||
return new RealDateTimeFormat(locale || defaultLocale, { ...options, timeZone: defaultTimezone });
|
||||
});
|
||||
};
|
||||
|
||||
export const unmockIntlDateTimeFormat = (): void => {
|
||||
jest.spyOn(global.Intl, "DateTimeFormat").mockRestore();
|
||||
vi.spyOn(globalThis.Intl, "DateTimeFormat").mockRestore();
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type RenderResult, screen, waitFor } from "jest-matrix-react";
|
||||
import { type RenderResult, screen, waitFor } from "test-utils-rtl";
|
||||
|
||||
export * from "./beacon";
|
||||
export * from "./client";
|
||||
|
||||
@@ -6,11 +6,13 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type MethodLikeKeys, mocked, type MockedObject } from "jest-mock";
|
||||
import { type MethodLikeKeys } from "jest-mock";
|
||||
import { type MockedObject } from "vitest";
|
||||
|
||||
import BasePlatform from "../../src/BasePlatform";
|
||||
import PlatformPeg from "../../src/PlatformPeg";
|
||||
import * as SessionLock from "../../src/utils/SessionLock";
|
||||
import { vi } from "../setup/adapter.ts";
|
||||
|
||||
// doesn't implement abstract
|
||||
// @ts-ignore
|
||||
@@ -38,10 +40,10 @@ export const mockPlatformPeg = (
|
||||
platformMocks: Partial<Record<MethodLikeKeys<BasePlatform>, unknown>> = {},
|
||||
): MockedObject<BasePlatform> => {
|
||||
const mockPlatform = new MockPlatform(platformMocks);
|
||||
jest.spyOn(PlatformPeg, "get").mockReturnValue(mockPlatform);
|
||||
return mocked(mockPlatform);
|
||||
vi.spyOn(PlatformPeg, "get").mockReturnValue(mockPlatform);
|
||||
return vi.mocked(mockPlatform);
|
||||
};
|
||||
|
||||
export const unmockPlatformPeg = () => {
|
||||
jest.spyOn(PlatformPeg, "get").mockRestore();
|
||||
vi.spyOn(PlatformPeg, "get").mockRestore();
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type Mocked } from "jest-mock";
|
||||
import { type Mocked } from "jest-mock-vitest-adapter";
|
||||
import {
|
||||
type MatrixClient,
|
||||
MatrixEvent,
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type MockedObject } from "jest-mock";
|
||||
import { type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import { type EventTimeline, EventType, type MatrixClient, type MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import EventEmitter from "events";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { type MockedObject } from "vitest";
|
||||
import {
|
||||
MatrixEvent,
|
||||
type Room,
|
||||
@@ -48,6 +48,7 @@ import { type ValidatedServerConfig } from "../../src/utils/ValidatedServerConfi
|
||||
import { EnhancedMap } from "../../src/utils/maps";
|
||||
import { type AsyncStoreWithClient } from "../../src/stores/AsyncStoreWithClient";
|
||||
import MatrixClientBackedSettingsHandler from "../../src/settings/handlers/MatrixClientBackedSettingsHandler";
|
||||
import { vi } from "../setup/adapter.ts";
|
||||
|
||||
/**
|
||||
* Stub out the MatrixClient, and configure the MatrixClientPeg object to
|
||||
@@ -66,10 +67,10 @@ export function stubClient(): MatrixClient {
|
||||
//
|
||||
// 'sandbox.restore()' doesn't work correctly on inherited methods,
|
||||
// so we do this for each method
|
||||
jest.spyOn(peg, "get");
|
||||
jest.spyOn(peg, "safeGet");
|
||||
jest.spyOn(peg, "unset");
|
||||
jest.spyOn(peg, "replaceUsingCreds");
|
||||
vi.spyOn(peg, "get");
|
||||
vi.spyOn(peg, "safeGet");
|
||||
vi.spyOn(peg, "unset");
|
||||
vi.spyOn(peg, "replaceUsingCreds");
|
||||
// MatrixClientPeg.safeGet() is called a /lot/, so implement it with our own
|
||||
// fast stub function rather than a sinon stub
|
||||
peg.get = () => client;
|
||||
@@ -90,64 +91,64 @@ export function createTestClient(): MatrixClient {
|
||||
let createdRoom: Room | undefined;
|
||||
|
||||
const client = {
|
||||
getHomeserverUrl: jest.fn(),
|
||||
getIdentityServerUrl: jest.fn(),
|
||||
getDomain: jest.fn().mockReturnValue("matrix.org"),
|
||||
getUserId: jest.fn().mockReturnValue("@userId:matrix.org"),
|
||||
getSafeUserId: jest.fn().mockReturnValue("@userId:matrix.org"),
|
||||
getUserIdLocalpart: jest.fn().mockResolvedValue("userId"),
|
||||
getUser: jest.fn().mockReturnValue({ on: jest.fn(), off: jest.fn() }),
|
||||
getDevice: jest.fn(),
|
||||
getDeviceId: jest.fn().mockReturnValue("ABCDEFGHI"),
|
||||
getHomeserverUrl: vi.fn(),
|
||||
getIdentityServerUrl: vi.fn(),
|
||||
getDomain: vi.fn().mockReturnValue("matrix.org"),
|
||||
getUserId: vi.fn().mockReturnValue("@userId:matrix.org"),
|
||||
getSafeUserId: vi.fn().mockReturnValue("@userId:matrix.org"),
|
||||
getUserIdLocalpart: vi.fn().mockResolvedValue("userId"),
|
||||
getUser: vi.fn().mockReturnValue({ on: vi.fn(), off: vi.fn() }),
|
||||
getDevice: vi.fn(),
|
||||
getDeviceId: vi.fn().mockReturnValue("ABCDEFGHI"),
|
||||
deviceId: "ABCDEFGHI",
|
||||
getDevices: jest.fn().mockResolvedValue({ devices: [{ device_id: "ABCDEFGHI" }] }),
|
||||
getSessionId: jest.fn().mockReturnValue("iaszphgvfku"),
|
||||
getDevices: vi.fn().mockResolvedValue({ devices: [{ device_id: "ABCDEFGHI" }] }),
|
||||
getSessionId: vi.fn().mockReturnValue("iaszphgvfku"),
|
||||
credentials: { userId: "@userId:matrix.org" },
|
||||
getAccessToken: jest.fn(),
|
||||
getAccessToken: vi.fn(),
|
||||
|
||||
secretStorage: {
|
||||
get: jest.fn(),
|
||||
isStored: jest.fn().mockReturnValue(false),
|
||||
checkKey: jest.fn().mockResolvedValue(false),
|
||||
hasKey: jest.fn().mockReturnValue(false),
|
||||
getDefaultKeyId: jest.fn().mockResolvedValue(null),
|
||||
get: vi.fn(),
|
||||
isStored: vi.fn().mockReturnValue(false),
|
||||
checkKey: vi.fn().mockResolvedValue(false),
|
||||
hasKey: vi.fn().mockReturnValue(false),
|
||||
getDefaultKeyId: vi.fn().mockResolvedValue(null),
|
||||
},
|
||||
|
||||
store: {
|
||||
getPendingEvents: jest.fn().mockResolvedValue([]),
|
||||
setPendingEvents: jest.fn().mockResolvedValue(undefined),
|
||||
storeRoom: jest.fn(),
|
||||
removeRoom: jest.fn(),
|
||||
getPendingEvents: vi.fn().mockResolvedValue([]),
|
||||
setPendingEvents: vi.fn().mockResolvedValue(undefined),
|
||||
storeRoom: vi.fn(),
|
||||
removeRoom: vi.fn(),
|
||||
},
|
||||
|
||||
getCrypto: jest.fn().mockReturnValue({
|
||||
getOwnDeviceKeys: jest.fn().mockResolvedValue({ ed25519: "ed25519", curve25519: "curve25519" }),
|
||||
getUserDeviceInfo: jest.fn().mockResolvedValue(new Map()),
|
||||
getUserVerificationStatus: jest.fn(),
|
||||
getDeviceVerificationStatus: jest.fn(),
|
||||
resetKeyBackup: jest.fn(),
|
||||
isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false),
|
||||
isStateEncryptionEnabledInRoom: jest.fn().mockResolvedValue(false),
|
||||
getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]),
|
||||
setDeviceIsolationMode: jest.fn(),
|
||||
prepareToEncrypt: jest.fn(),
|
||||
bootstrapCrossSigning: jest.fn(),
|
||||
getActiveSessionBackupVersion: jest.fn().mockResolvedValue(null),
|
||||
isKeyBackupTrusted: jest.fn().mockResolvedValue({}),
|
||||
createRecoveryKeyFromPassphrase: jest.fn().mockResolvedValue({
|
||||
getCrypto: vi.fn().mockReturnValue({
|
||||
getOwnDeviceKeys: vi.fn().mockResolvedValue({ ed25519: "ed25519", curve25519: "curve25519" }),
|
||||
getUserDeviceInfo: vi.fn().mockResolvedValue(new Map()),
|
||||
getUserVerificationStatus: vi.fn(),
|
||||
getDeviceVerificationStatus: vi.fn(),
|
||||
resetKeyBackup: vi.fn(),
|
||||
isEncryptionEnabledInRoom: vi.fn().mockResolvedValue(false),
|
||||
isStateEncryptionEnabledInRoom: vi.fn().mockResolvedValue(false),
|
||||
getVerificationRequestsToDeviceInProgress: vi.fn().mockReturnValue([]),
|
||||
setDeviceIsolationMode: vi.fn(),
|
||||
prepareToEncrypt: vi.fn(),
|
||||
bootstrapCrossSigning: vi.fn(),
|
||||
getActiveSessionBackupVersion: vi.fn().mockResolvedValue(null),
|
||||
isKeyBackupTrusted: vi.fn().mockResolvedValue({}),
|
||||
createRecoveryKeyFromPassphrase: vi.fn().mockResolvedValue({
|
||||
privateKey: new Uint8Array(32),
|
||||
encodedPrivateKey: "encoded private key",
|
||||
}),
|
||||
bootstrapSecretStorage: jest.fn(),
|
||||
isDehydrationSupported: jest.fn().mockResolvedValue(false),
|
||||
restoreKeyBackup: jest.fn(),
|
||||
restoreKeyBackupWithPassphrase: jest.fn(),
|
||||
loadSessionBackupPrivateKeyFromSecretStorage: jest.fn(),
|
||||
storeSessionBackupPrivateKey: jest.fn(),
|
||||
checkKeyBackupAndEnable: jest.fn().mockResolvedValue(null),
|
||||
getKeyBackupInfo: jest.fn().mockResolvedValue(null),
|
||||
getEncryptionInfoForEvent: jest.fn().mockResolvedValue(null),
|
||||
getCrossSigningStatus: jest.fn().mockResolvedValue({
|
||||
bootstrapSecretStorage: vi.fn(),
|
||||
isDehydrationSupported: vi.fn().mockResolvedValue(false),
|
||||
restoreKeyBackup: vi.fn(),
|
||||
restoreKeyBackupWithPassphrase: vi.fn(),
|
||||
loadSessionBackupPrivateKeyFromSecretStorage: vi.fn(),
|
||||
storeSessionBackupPrivateKey: vi.fn(),
|
||||
checkKeyBackupAndEnable: vi.fn().mockResolvedValue(null),
|
||||
getKeyBackupInfo: vi.fn().mockResolvedValue(null),
|
||||
getEncryptionInfoForEvent: vi.fn().mockResolvedValue(null),
|
||||
getCrossSigningStatus: vi.fn().mockResolvedValue({
|
||||
publicKeysOnDevice: false,
|
||||
privateKeysInSecretStorage: false,
|
||||
privateKeysCachedLocally: {
|
||||
@@ -156,17 +157,17 @@ export function createTestClient(): MatrixClient {
|
||||
userSigningKey: false,
|
||||
},
|
||||
}),
|
||||
isCrossSigningReady: jest.fn().mockResolvedValue(false),
|
||||
disableKeyStorage: jest.fn(),
|
||||
resetEncryption: jest.fn(),
|
||||
getSessionBackupPrivateKey: jest.fn().mockResolvedValue(null),
|
||||
isSecretStorageReady: jest.fn().mockResolvedValue(false),
|
||||
deleteKeyBackupVersion: jest.fn(),
|
||||
crossSignDevice: jest.fn(),
|
||||
isCrossSigningReady: vi.fn().mockResolvedValue(false),
|
||||
disableKeyStorage: vi.fn(),
|
||||
resetEncryption: vi.fn(),
|
||||
getSessionBackupPrivateKey: vi.fn().mockResolvedValue(null),
|
||||
isSecretStorageReady: vi.fn().mockResolvedValue(false),
|
||||
deleteKeyBackupVersion: vi.fn(),
|
||||
crossSignDevice: vi.fn(),
|
||||
}),
|
||||
|
||||
getPushActionsForEvent: jest.fn(),
|
||||
getRoom: jest.fn().mockImplementation((roomId) => {
|
||||
getPushActionsForEvent: vi.fn(),
|
||||
getRoom: vi.fn().mockImplementation((roomId) => {
|
||||
// If the test called `createRoom`, return the mocked room it created.
|
||||
if (createdRoom) {
|
||||
return createdRoom;
|
||||
@@ -174,32 +175,32 @@ export function createTestClient(): MatrixClient {
|
||||
return mkStubRoom(roomId, "My room", client);
|
||||
}
|
||||
}),
|
||||
getRooms: jest.fn().mockReturnValue([]),
|
||||
getVisibleRooms: jest.fn().mockReturnValue([]),
|
||||
loginFlows: jest.fn(),
|
||||
getRooms: vi.fn().mockReturnValue([]),
|
||||
getVisibleRooms: vi.fn().mockReturnValue([]),
|
||||
loginFlows: vi.fn(),
|
||||
on: eventEmitter.on.bind(eventEmitter),
|
||||
once: eventEmitter.once.bind(eventEmitter),
|
||||
off: eventEmitter.off.bind(eventEmitter),
|
||||
removeListener: eventEmitter.removeListener.bind(eventEmitter),
|
||||
emit: eventEmitter.emit.bind(eventEmitter),
|
||||
isRoomEncrypted: jest.fn().mockReturnValue(false),
|
||||
peekInRoom: jest.fn().mockResolvedValue(mkStubRoom(undefined, undefined, undefined)),
|
||||
stopPeeking: jest.fn(),
|
||||
isRoomEncrypted: vi.fn().mockReturnValue(false),
|
||||
peekInRoom: vi.fn().mockResolvedValue(mkStubRoom(undefined, undefined, undefined)),
|
||||
stopPeeking: vi.fn(),
|
||||
|
||||
getEventTimeline: jest.fn().mockResolvedValue([]),
|
||||
paginateEventTimeline: jest.fn().mockResolvedValue(undefined),
|
||||
sendReadReceipt: jest.fn().mockResolvedValue(undefined),
|
||||
getRoomIdForAlias: jest.fn().mockResolvedValue(undefined),
|
||||
getRoomDirectoryVisibility: jest.fn().mockResolvedValue(undefined),
|
||||
getProfileInfo: jest.fn().mockResolvedValue({}),
|
||||
getThirdpartyProtocols: jest.fn().mockResolvedValue({}),
|
||||
getClientWellKnown: jest.fn().mockReturnValue(null),
|
||||
waitForClientWellKnown: jest.fn().mockResolvedValue({}),
|
||||
supportsVoip: jest.fn().mockReturnValue(true),
|
||||
getTurnServers: jest.fn().mockReturnValue([]),
|
||||
getTurnServersExpiry: jest.fn().mockReturnValue(2 ^ 32),
|
||||
getThirdpartyUser: jest.fn().mockResolvedValue([]),
|
||||
getAccountData: jest.fn().mockImplementation((type) => {
|
||||
getEventTimeline: vi.fn().mockResolvedValue([]),
|
||||
paginateEventTimeline: vi.fn().mockResolvedValue(undefined),
|
||||
sendReadReceipt: vi.fn().mockResolvedValue(undefined),
|
||||
getRoomIdForAlias: vi.fn().mockResolvedValue(undefined),
|
||||
getRoomDirectoryVisibility: vi.fn().mockResolvedValue(undefined),
|
||||
getProfileInfo: vi.fn().mockResolvedValue({}),
|
||||
getThirdpartyProtocols: vi.fn().mockResolvedValue({}),
|
||||
getClientWellKnown: vi.fn().mockReturnValue(null),
|
||||
waitForClientWellKnown: vi.fn().mockResolvedValue({}),
|
||||
supportsVoip: vi.fn().mockReturnValue(true),
|
||||
getTurnServers: vi.fn().mockReturnValue([]),
|
||||
getTurnServersExpiry: vi.fn().mockReturnValue(2 ^ 32),
|
||||
getThirdpartyUser: vi.fn().mockResolvedValue([]),
|
||||
getAccountData: vi.fn().mockImplementation((type) => {
|
||||
return mkEvent({
|
||||
user: "@user:example.com",
|
||||
room: undefined,
|
||||
@@ -208,26 +209,26 @@ export function createTestClient(): MatrixClient {
|
||||
content: {},
|
||||
});
|
||||
}),
|
||||
getAccountDataFromServer: jest.fn(),
|
||||
getAccountDataFromServer: vi.fn(),
|
||||
|
||||
mxcUrlToHttp: jest.fn().mockImplementation((mxc: string) => `http://this.is.a.url/${mxc.substring(6)}`),
|
||||
setAccountData: jest.fn(),
|
||||
deleteAccountData: jest.fn(),
|
||||
setRoomAccountData: jest.fn(),
|
||||
setRoomName: jest.fn(),
|
||||
setRoomTopic: jest.fn(),
|
||||
setRoomReadMarkers: jest.fn().mockResolvedValue({}),
|
||||
sendTyping: jest.fn().mockResolvedValue({}),
|
||||
sendMessage: jest.fn().mockResolvedValue({}),
|
||||
sendStateEvent: jest.fn().mockResolvedValue(undefined),
|
||||
sendRtcDecline: jest.fn().mockResolvedValue(undefined),
|
||||
getSyncState: jest.fn().mockReturnValue("SYNCING"),
|
||||
mxcUrlToHttp: vi.fn().mockImplementation((mxc: string) => `http://this.is.a.url/${mxc.substring(6)}`),
|
||||
setAccountData: vi.fn(),
|
||||
deleteAccountData: vi.fn(),
|
||||
setRoomAccountData: vi.fn(),
|
||||
setRoomName: vi.fn(),
|
||||
setRoomTopic: vi.fn(),
|
||||
setRoomReadMarkers: vi.fn().mockResolvedValue({}),
|
||||
sendTyping: vi.fn().mockResolvedValue({}),
|
||||
sendMessage: vi.fn().mockResolvedValue({}),
|
||||
sendStateEvent: vi.fn().mockResolvedValue(undefined),
|
||||
sendRtcDecline: vi.fn().mockResolvedValue(undefined),
|
||||
getSyncState: vi.fn().mockReturnValue("SYNCING"),
|
||||
generateClientSecret: () => "t35tcl1Ent5ECr3T",
|
||||
isGuest: jest.fn().mockReturnValue(false),
|
||||
getRoomHierarchy: jest.fn().mockReturnValue({
|
||||
isGuest: vi.fn().mockReturnValue(false),
|
||||
getRoomHierarchy: vi.fn().mockReturnValue({
|
||||
rooms: [],
|
||||
}),
|
||||
createRoom: jest.fn(async (createOpts?: ICreateRoomOpts) => {
|
||||
createRoom: vi.fn(async (createOpts?: ICreateRoomOpts) => {
|
||||
const initialState = createOpts?.initial_state?.map((event, i) =>
|
||||
mkEvent({
|
||||
...event,
|
||||
@@ -244,60 +245,60 @@ export function createTestClient(): MatrixClient {
|
||||
);
|
||||
return { room_id: "!1:example.org" };
|
||||
}),
|
||||
setPowerLevel: jest.fn().mockResolvedValue(undefined),
|
||||
setPowerLevel: vi.fn().mockResolvedValue(undefined),
|
||||
pushRules: {},
|
||||
decryptEventIfNeeded: () => Promise.resolve(),
|
||||
isUserIgnored: jest.fn().mockReturnValue(false),
|
||||
getCapabilities: jest.fn().mockResolvedValue({}),
|
||||
getCachedCapabilities: jest.fn().mockReturnValue({}),
|
||||
supportsThreads: jest.fn().mockReturnValue(false),
|
||||
supportsIntentionalMentions: jest.fn().mockReturnValue(false),
|
||||
getRoomUpgradeHistory: jest.fn().mockReturnValue([]),
|
||||
getOpenIdToken: jest.fn().mockResolvedValue(undefined),
|
||||
registerWithIdentityServer: jest.fn().mockResolvedValue({}),
|
||||
getIdentityAccount: jest.fn().mockResolvedValue({}),
|
||||
getTerms: jest.fn().mockResolvedValue({ policies: [] }),
|
||||
agreeToTerms: jest.fn(),
|
||||
doesServerSupportUnstableFeature: jest.fn().mockResolvedValue(undefined),
|
||||
isVersionSupported: jest.fn().mockResolvedValue(undefined),
|
||||
getPushRules: jest.fn().mockResolvedValue(undefined),
|
||||
getPushers: jest.fn().mockResolvedValue({ pushers: [] }),
|
||||
getThreePids: jest.fn().mockResolvedValue({ threepids: [] }),
|
||||
bulkLookupThreePids: jest.fn().mockResolvedValue({ threepids: [] }),
|
||||
setAvatarUrl: jest.fn().mockResolvedValue(undefined),
|
||||
setDisplayName: jest.fn().mockResolvedValue(undefined),
|
||||
setPusher: jest.fn().mockResolvedValue(undefined),
|
||||
setPushRuleEnabled: jest.fn().mockResolvedValue(undefined),
|
||||
setPushRuleActions: jest.fn().mockResolvedValue(undefined),
|
||||
relations: jest.fn().mockResolvedValue({
|
||||
isUserIgnored: vi.fn().mockReturnValue(false),
|
||||
getCapabilities: vi.fn().mockResolvedValue({}),
|
||||
getCachedCapabilities: vi.fn().mockReturnValue({}),
|
||||
supportsThreads: vi.fn().mockReturnValue(false),
|
||||
supportsIntentionalMentions: vi.fn().mockReturnValue(false),
|
||||
getRoomUpgradeHistory: vi.fn().mockReturnValue([]),
|
||||
getOpenIdToken: vi.fn().mockResolvedValue(undefined),
|
||||
registerWithIdentityServer: vi.fn().mockResolvedValue({}),
|
||||
getIdentityAccount: vi.fn().mockResolvedValue({}),
|
||||
getTerms: vi.fn().mockResolvedValue({ policies: [] }),
|
||||
agreeToTerms: vi.fn(),
|
||||
doesServerSupportUnstableFeature: vi.fn().mockResolvedValue(undefined),
|
||||
isVersionSupported: vi.fn().mockResolvedValue(undefined),
|
||||
getPushRules: vi.fn().mockResolvedValue(undefined),
|
||||
getPushers: vi.fn().mockResolvedValue({ pushers: [] }),
|
||||
getThreePids: vi.fn().mockResolvedValue({ threepids: [] }),
|
||||
bulkLookupThreePids: vi.fn().mockResolvedValue({ threepids: [] }),
|
||||
setAvatarUrl: vi.fn().mockResolvedValue(undefined),
|
||||
setDisplayName: vi.fn().mockResolvedValue(undefined),
|
||||
setPusher: vi.fn().mockResolvedValue(undefined),
|
||||
setPushRuleEnabled: vi.fn().mockResolvedValue(undefined),
|
||||
setPushRuleActions: vi.fn().mockResolvedValue(undefined),
|
||||
relations: vi.fn().mockResolvedValue({
|
||||
events: [],
|
||||
}),
|
||||
hasLazyLoadMembersEnabled: jest.fn().mockReturnValue(false),
|
||||
isInitialSyncComplete: jest.fn().mockReturnValue(true),
|
||||
fetchRoomEvent: jest.fn().mockRejectedValue({}),
|
||||
makeTxnId: jest.fn().mockImplementation(() => `t${txnId++}`),
|
||||
sendToDevice: jest.fn().mockResolvedValue(undefined),
|
||||
queueToDevice: jest.fn().mockResolvedValue(undefined),
|
||||
cancelPendingEvent: jest.fn(),
|
||||
hasLazyLoadMembersEnabled: vi.fn().mockReturnValue(false),
|
||||
isInitialSyncComplete: vi.fn().mockReturnValue(true),
|
||||
fetchRoomEvent: vi.fn().mockRejectedValue({}),
|
||||
makeTxnId: vi.fn().mockImplementation(() => `t${txnId++}`),
|
||||
sendToDevice: vi.fn().mockResolvedValue(undefined),
|
||||
queueToDevice: vi.fn().mockResolvedValue(undefined),
|
||||
cancelPendingEvent: vi.fn(),
|
||||
|
||||
getMediaHandler: jest.fn().mockReturnValue({
|
||||
setVideoInput: jest.fn(),
|
||||
setAudioInput: jest.fn(),
|
||||
setAudioSettings: jest.fn(),
|
||||
stopAllStreams: jest.fn(),
|
||||
getMediaHandler: vi.fn().mockReturnValue({
|
||||
setVideoInput: vi.fn(),
|
||||
setAudioInput: vi.fn(),
|
||||
setAudioSettings: vi.fn(),
|
||||
stopAllStreams: vi.fn(),
|
||||
} as unknown as MediaHandler),
|
||||
uploadContent: jest.fn(),
|
||||
uploadContent: vi.fn(),
|
||||
getEventMapper: (_options?: MapperOpts) => (event: Partial<IEvent>) => new MatrixEvent(event),
|
||||
leaveRoomChain: jest.fn((roomId) => ({ [roomId]: null })),
|
||||
requestPasswordEmailToken: jest.fn().mockRejectedValue({}),
|
||||
setPassword: jest.fn().mockRejectedValue({}),
|
||||
leaveRoomChain: vi.fn((roomId) => ({ [roomId]: null })),
|
||||
requestPasswordEmailToken: vi.fn().mockRejectedValue({}),
|
||||
setPassword: vi.fn().mockRejectedValue({}),
|
||||
groupCallEventHandler: { groupCalls: new Map<string, GroupCall>() },
|
||||
redactEvent: jest.fn(),
|
||||
redactEvent: vi.fn(),
|
||||
|
||||
createMessagesRequest: jest.fn().mockResolvedValue({
|
||||
createMessagesRequest: vi.fn().mockResolvedValue({
|
||||
chunk: [],
|
||||
}),
|
||||
sendEvent: jest.fn().mockImplementation((roomId, type, content) => {
|
||||
sendEvent: vi.fn().mockImplementation((roomId, type, content) => {
|
||||
return new MatrixEvent({
|
||||
type,
|
||||
sender: "@me:localhost",
|
||||
@@ -306,61 +307,61 @@ export function createTestClient(): MatrixClient {
|
||||
room_id: roomId,
|
||||
});
|
||||
}),
|
||||
resendEvent: jest.fn().mockResolvedValue({}),
|
||||
resendEvent: vi.fn().mockResolvedValue({}),
|
||||
|
||||
_unstable_sendDelayedEvent: jest.fn(),
|
||||
_unstable_sendDelayedStateEvent: jest.fn(),
|
||||
_unstable_cancelScheduledDelayedEvent: jest.fn(),
|
||||
_unstable_restartScheduledDelayedEvent: jest.fn(),
|
||||
_unstable_sendScheduledDelayedEvent: jest.fn(),
|
||||
_unstable_sendStickyEvent: jest.fn(),
|
||||
_unstable_sendStickyDelayedEvent: jest.fn(),
|
||||
_unstable_getRTCTransports: jest.fn(),
|
||||
searchUserDirectory: jest.fn().mockResolvedValue({ limited: false, results: [] }),
|
||||
setDeviceVerified: jest.fn(),
|
||||
joinRoom: jest.fn(),
|
||||
getSyncStateData: jest.fn(),
|
||||
getDehydratedDevice: jest.fn(),
|
||||
exportRoomKeys: jest.fn(),
|
||||
knockRoom: jest.fn(),
|
||||
leave: jest.fn(),
|
||||
getVersions: jest.fn().mockResolvedValue({ versions: ["v1.1"] }),
|
||||
requestAdd3pidEmailToken: jest.fn(),
|
||||
requestAdd3pidMsisdnToken: jest.fn(),
|
||||
submitMsisdnTokenOtherUrl: jest.fn(),
|
||||
deleteThreePid: jest.fn().mockResolvedValue({}),
|
||||
bindThreePid: jest.fn().mockResolvedValue({}),
|
||||
unbindThreePid: jest.fn().mockResolvedValue({}),
|
||||
requestEmailToken: jest.fn(),
|
||||
addThreePidOnly: jest.fn(),
|
||||
requestMsisdnToken: jest.fn(),
|
||||
submitMsisdnToken: jest.fn(),
|
||||
getMediaConfig: jest.fn(),
|
||||
_unstable_sendDelayedEvent: vi.fn(),
|
||||
_unstable_sendDelayedStateEvent: vi.fn(),
|
||||
_unstable_cancelScheduledDelayedEvent: vi.fn(),
|
||||
_unstable_restartScheduledDelayedEvent: vi.fn(),
|
||||
_unstable_sendScheduledDelayedEvent: vi.fn(),
|
||||
_unstable_sendStickyEvent: vi.fn(),
|
||||
_unstable_sendStickyDelayedEvent: vi.fn(),
|
||||
_unstable_getRTCTransports: vi.fn(),
|
||||
searchUserDirectory: vi.fn().mockResolvedValue({ limited: false, results: [] }),
|
||||
setDeviceVerified: vi.fn(),
|
||||
joinRoom: vi.fn(),
|
||||
getSyncStateData: vi.fn(),
|
||||
getDehydratedDevice: vi.fn(),
|
||||
exportRoomKeys: vi.fn(),
|
||||
knockRoom: vi.fn(),
|
||||
leave: vi.fn(),
|
||||
getVersions: vi.fn().mockResolvedValue({ versions: ["v1.1"] }),
|
||||
requestAdd3pidEmailToken: vi.fn(),
|
||||
requestAdd3pidMsisdnToken: vi.fn(),
|
||||
submitMsisdnTokenOtherUrl: vi.fn(),
|
||||
deleteThreePid: vi.fn().mockResolvedValue({}),
|
||||
bindThreePid: vi.fn().mockResolvedValue({}),
|
||||
unbindThreePid: vi.fn().mockResolvedValue({}),
|
||||
requestEmailToken: vi.fn(),
|
||||
addThreePidOnly: vi.fn(),
|
||||
requestMsisdnToken: vi.fn(),
|
||||
submitMsisdnToken: vi.fn(),
|
||||
getMediaConfig: vi.fn(),
|
||||
baseUrl: "https://matrix-client.matrix.org",
|
||||
matrixRTC: createStubMatrixRTC(),
|
||||
isFallbackICEServerAllowed: jest.fn().mockReturnValue(false),
|
||||
getAuthIssuer: jest.fn(),
|
||||
getOrCreateFilter: jest.fn(),
|
||||
sendStickerMessage: jest.fn(),
|
||||
getLocalAliases: jest.fn().mockReturnValue([]),
|
||||
uploadDeviceSigningKeys: jest.fn(),
|
||||
isKeyBackupKeyStored: jest.fn().mockResolvedValue(null),
|
||||
getIgnoredUsers: jest.fn().mockReturnValue([]),
|
||||
setIgnoredUsers: jest.fn(),
|
||||
reportRoom: jest.fn(),
|
||||
isFallbackICEServerAllowed: vi.fn().mockReturnValue(false),
|
||||
getAuthIssuer: vi.fn(),
|
||||
getOrCreateFilter: vi.fn(),
|
||||
sendStickerMessage: vi.fn(),
|
||||
getLocalAliases: vi.fn().mockReturnValue([]),
|
||||
uploadDeviceSigningKeys: vi.fn(),
|
||||
isKeyBackupKeyStored: vi.fn().mockResolvedValue(null),
|
||||
getIgnoredUsers: vi.fn().mockReturnValue([]),
|
||||
setIgnoredUsers: vi.fn(),
|
||||
reportRoom: vi.fn(),
|
||||
pushProcessor: {
|
||||
getPushRuleById: jest.fn(),
|
||||
getPushRuleById: vi.fn(),
|
||||
},
|
||||
search: jest.fn().mockResolvedValue({}),
|
||||
processRoomEventsSearch: jest.fn().mockResolvedValue({ highlights: [], results: [] }),
|
||||
invite: jest.fn(),
|
||||
kick: jest.fn(),
|
||||
ban: jest.fn(),
|
||||
sendTextMessage: jest.fn(),
|
||||
deleteRoomTag: jest.fn().mockResolvedValue({}),
|
||||
setRoomTag: jest.fn().mockResolvedValue({}),
|
||||
getExtendedProfileProperty: jest.fn(),
|
||||
setExtendedProfileProperty: jest.fn().mockResolvedValue(undefined),
|
||||
search: vi.fn().mockResolvedValue({}),
|
||||
processRoomEventsSearch: vi.fn().mockResolvedValue({ highlights: [], results: [] }),
|
||||
invite: vi.fn(),
|
||||
kick: vi.fn(),
|
||||
ban: vi.fn(),
|
||||
sendTextMessage: vi.fn(),
|
||||
deleteRoomTag: vi.fn().mockResolvedValue({}),
|
||||
setRoomTag: vi.fn().mockResolvedValue({}),
|
||||
getExtendedProfileProperty: vi.fn(),
|
||||
setExtendedProfileProperty: vi.fn().mockResolvedValue(undefined),
|
||||
} as unknown as MatrixClient;
|
||||
|
||||
client.reEmitter = new ReEmitter(client);
|
||||
@@ -379,7 +380,7 @@ export function createTestClient(): MatrixClient {
|
||||
|
||||
export function createStubMatrixRTC(): MatrixRTCSessionManager {
|
||||
const eventEmitterMatrixRTCSessionManager = new EventEmitter();
|
||||
const mockGetRoomSession = jest.fn();
|
||||
const mockGetRoomSession = vi.fn();
|
||||
mockGetRoomSession.mockImplementation((roomId) => {
|
||||
const session = new EventEmitter() as MatrixRTCSession;
|
||||
session.memberships = [];
|
||||
@@ -388,9 +389,9 @@ export function createStubMatrixRTC(): MatrixRTCSessionManager {
|
||||
return session;
|
||||
});
|
||||
return {
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
getActiveRoomSession: jest.fn(),
|
||||
start: vi.fn(),
|
||||
stop: vi.fn(),
|
||||
getActiveRoomSession: vi.fn(),
|
||||
getRoomSession: mockGetRoomSession,
|
||||
on: eventEmitterMatrixRTCSessionManager.on.bind(eventEmitterMatrixRTCSessionManager),
|
||||
off: eventEmitterMatrixRTCSessionManager.off.bind(eventEmitterMatrixRTCSessionManager),
|
||||
@@ -673,42 +674,42 @@ export function mkStubRoom(
|
||||
const eventEmitter = new EventEmitter();
|
||||
|
||||
return {
|
||||
canInvite: jest.fn().mockReturnValue(false),
|
||||
canInvite: vi.fn().mockReturnValue(false),
|
||||
client,
|
||||
findThreadForEvent: jest.fn(),
|
||||
createThreadsTimelineSets: jest.fn().mockReturnValue(new Promise(() => {})),
|
||||
findThreadForEvent: vi.fn(),
|
||||
createThreadsTimelineSets: vi.fn().mockReturnValue(new Promise(() => {})),
|
||||
currentState: {
|
||||
getStateEvents: jest.fn((_type, key) => (key === undefined ? [] : null)),
|
||||
getMember: jest.fn(),
|
||||
mayClientSendStateEvent: jest.fn().mockReturnValue(true),
|
||||
maySendStateEvent: jest.fn().mockReturnValue(true),
|
||||
maySendRedactionForEvent: jest.fn().mockReturnValue(true),
|
||||
maySendEvent: jest.fn().mockReturnValue(true),
|
||||
maySendMessage: jest.fn().mockReturnValue(true),
|
||||
getStateEvents: vi.fn((_type, key) => (key === undefined ? [] : null)),
|
||||
getMember: vi.fn(),
|
||||
mayClientSendStateEvent: vi.fn().mockReturnValue(true),
|
||||
maySendStateEvent: vi.fn().mockReturnValue(true),
|
||||
maySendRedactionForEvent: vi.fn().mockReturnValue(true),
|
||||
maySendEvent: vi.fn().mockReturnValue(true),
|
||||
maySendMessage: vi.fn().mockReturnValue(true),
|
||||
members: {},
|
||||
getHistoryVisibility: jest.fn().mockReturnValue(HistoryVisibility.Shared),
|
||||
getJoinRule: jest.fn().mockReturnValue(JoinRule.Invite),
|
||||
on: jest.fn(),
|
||||
off: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
getHistoryVisibility: vi.fn().mockReturnValue(HistoryVisibility.Shared),
|
||||
getJoinRule: vi.fn().mockReturnValue(JoinRule.Invite),
|
||||
on: vi.fn(),
|
||||
off: vi.fn(),
|
||||
removeListener: vi.fn(),
|
||||
} as unknown as RoomState,
|
||||
eventShouldLiveIn: jest.fn().mockReturnValue({ shouldLiveInRoom: true, shouldLiveInThread: false }),
|
||||
fetchRoomThreads: jest.fn().mockReturnValue(Promise.resolve()),
|
||||
findEventById: jest.fn().mockReturnValue(undefined),
|
||||
findPredecessor: jest.fn().mockReturnValue({ roomId: "", eventId: null }),
|
||||
getAltAliases: jest.fn().mockReturnValue([]),
|
||||
eventShouldLiveIn: vi.fn().mockReturnValue({ shouldLiveInRoom: true, shouldLiveInThread: false }),
|
||||
fetchRoomThreads: vi.fn().mockReturnValue(Promise.resolve()),
|
||||
findEventById: vi.fn().mockReturnValue(undefined),
|
||||
findPredecessor: vi.fn().mockReturnValue({ roomId: "", eventId: null }),
|
||||
getAltAliases: vi.fn().mockReturnValue([]),
|
||||
getAvatarUrl: () => "mxc://avatar.url/room.png",
|
||||
getCanonicalAlias: jest.fn(),
|
||||
getDMInviter: jest.fn(),
|
||||
getEventReadUpTo: jest.fn(() => null),
|
||||
getInvitedAndJoinedMemberCount: jest.fn().mockReturnValue(1),
|
||||
getJoinRule: jest.fn().mockReturnValue("invite"),
|
||||
getJoinedMemberCount: jest.fn().mockReturnValue(1),
|
||||
getJoinedMembers: jest.fn().mockReturnValue([]),
|
||||
getLiveTimeline: jest.fn().mockReturnValue(stubTimeline),
|
||||
getLastLiveEvent: jest.fn().mockReturnValue(undefined),
|
||||
getLastActiveTimestamp: jest.fn().mockReturnValue(1183140000),
|
||||
getMember: jest.fn().mockReturnValue({
|
||||
getCanonicalAlias: vi.fn(),
|
||||
getDMInviter: vi.fn(),
|
||||
getEventReadUpTo: vi.fn(() => null),
|
||||
getInvitedAndJoinedMemberCount: vi.fn().mockReturnValue(1),
|
||||
getJoinRule: vi.fn().mockReturnValue("invite"),
|
||||
getJoinedMemberCount: vi.fn().mockReturnValue(1),
|
||||
getJoinedMembers: vi.fn().mockReturnValue([]),
|
||||
getLiveTimeline: vi.fn().mockReturnValue(stubTimeline),
|
||||
getLastLiveEvent: vi.fn().mockReturnValue(undefined),
|
||||
getLastActiveTimestamp: vi.fn().mockReturnValue(1183140000),
|
||||
getMember: vi.fn().mockReturnValue({
|
||||
userId: "@member:domain.bla",
|
||||
name: "Member",
|
||||
rawDisplayName: "Member",
|
||||
@@ -718,29 +719,29 @@ export function mkStubRoom(
|
||||
events: {},
|
||||
isKicked: () => false,
|
||||
}),
|
||||
getMembers: jest.fn().mockReturnValue([]),
|
||||
getEncryptionTargetMembers: jest.fn().mockReturnValue([]),
|
||||
getMembersWithMembership: jest.fn().mockReturnValue([]),
|
||||
getMembers: vi.fn().mockReturnValue([]),
|
||||
getEncryptionTargetMembers: vi.fn().mockReturnValue([]),
|
||||
getMembersWithMembership: vi.fn().mockReturnValue([]),
|
||||
getMxcAvatarUrl: () => "mxc://avatar.url/room.png",
|
||||
getMyMembership: jest.fn().mockReturnValue(KnownMembership.Join),
|
||||
getPendingEvents: jest.fn().mockReturnValue([]),
|
||||
getReceiptsForEvent: jest.fn().mockReturnValue([]),
|
||||
getRecommendedVersion: jest.fn().mockReturnValue(Promise.resolve("")),
|
||||
getThreads: jest.fn().mockReturnValue([]),
|
||||
getType: jest.fn().mockReturnValue(undefined),
|
||||
getUnfilteredTimelineSet: jest.fn(),
|
||||
getUnreadNotificationCount: jest.fn(() => 0),
|
||||
getRoomUnreadNotificationCount: jest.fn().mockReturnValue(0),
|
||||
getVersion: jest.fn().mockReturnValue("1"),
|
||||
getBumpStamp: jest.fn().mockReturnValue(0),
|
||||
getAccountData: jest.fn(),
|
||||
getMyMembership: vi.fn().mockReturnValue(KnownMembership.Join),
|
||||
getPendingEvents: vi.fn().mockReturnValue([]),
|
||||
getReceiptsForEvent: vi.fn().mockReturnValue([]),
|
||||
getRecommendedVersion: vi.fn().mockReturnValue(Promise.resolve("")),
|
||||
getThreads: vi.fn().mockReturnValue([]),
|
||||
getType: vi.fn().mockReturnValue(undefined),
|
||||
getUnfilteredTimelineSet: vi.fn(),
|
||||
getUnreadNotificationCount: vi.fn(() => 0),
|
||||
getRoomUnreadNotificationCount: vi.fn().mockReturnValue(0),
|
||||
getVersion: vi.fn().mockReturnValue("1"),
|
||||
getBumpStamp: vi.fn().mockReturnValue(0),
|
||||
getAccountData: vi.fn(),
|
||||
hasMembershipState: () => false,
|
||||
isElementVideoRoom: jest.fn().mockReturnValue(false),
|
||||
isSpaceRoom: jest.fn().mockReturnValue(false),
|
||||
isCallRoom: jest.fn().mockReturnValue(false),
|
||||
hasEncryptionStateEvent: jest.fn().mockReturnValue(false),
|
||||
loadMembersIfNeeded: jest.fn(),
|
||||
maySendMessage: jest.fn().mockReturnValue(true),
|
||||
isElementVideoRoom: vi.fn().mockReturnValue(false),
|
||||
isSpaceRoom: vi.fn().mockReturnValue(false),
|
||||
isCallRoom: vi.fn().mockReturnValue(false),
|
||||
hasEncryptionStateEvent: vi.fn().mockReturnValue(false),
|
||||
loadMembersIfNeeded: vi.fn(),
|
||||
maySendMessage: vi.fn().mockReturnValue(true),
|
||||
myUserId: client?.getUserId(),
|
||||
name,
|
||||
normalizedName: normalize(name || ""),
|
||||
@@ -750,8 +751,8 @@ export function mkStubRoom(
|
||||
removeListener: eventEmitter.removeListener.bind(eventEmitter),
|
||||
emit: eventEmitter.emit.bind(eventEmitter),
|
||||
roomId,
|
||||
setBlacklistUnverifiedDevices: jest.fn(),
|
||||
setUnreadNotificationCount: jest.fn(),
|
||||
setBlacklistUnverifiedDevices: vi.fn(),
|
||||
setUnreadNotificationCount: vi.fn(),
|
||||
tags: {},
|
||||
timeline: [],
|
||||
} as unknown as Room;
|
||||
@@ -828,8 +829,8 @@ export const mkRoom = (
|
||||
roomId: string,
|
||||
rooms?: ReturnType<typeof mkStubRoom>[],
|
||||
): MockedObject<Room> => {
|
||||
const room = mocked(mkStubRoom(roomId, roomId, client));
|
||||
mocked(room.currentState).getStateEvents.mockImplementation(mockStateEventImplementation([]));
|
||||
const room = vi.mocked(mkStubRoom(roomId, roomId, client));
|
||||
vi.mocked(room.currentState).getStateEvents.mockImplementation(mockStateEventImplementation([]));
|
||||
rooms?.push(room);
|
||||
return room;
|
||||
};
|
||||
@@ -858,10 +859,10 @@ export const mkSpace = (
|
||||
rooms?: ReturnType<typeof mkStubRoom>[],
|
||||
children: string[] = [],
|
||||
): MockedObject<Room> => {
|
||||
const space = mocked(mkRoom(client, spaceId, rooms));
|
||||
const space = vi.mocked(mkRoom(client, spaceId, rooms));
|
||||
space.isSpaceRoom.mockReturnValue(true);
|
||||
space.getType.mockReturnValue(RoomType.Space);
|
||||
mocked(space.currentState).getStateEvents.mockImplementation(
|
||||
vi.mocked(space.currentState).getStateEvents.mockImplementation(
|
||||
mockStateEventImplementation(
|
||||
children.map((roomId) =>
|
||||
mkEvent({
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { act } from "jest-matrix-react";
|
||||
import { act } from "test-utils-rtl";
|
||||
|
||||
import type EventEmitter from "events";
|
||||
import { type ActionPayload } from "../../src/dispatcher/payloads";
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type Mocked, mocked, type MockedObject } from "jest-mock";
|
||||
import { type Mocked, mocked } from "jest-mock-vitest-adapter";
|
||||
import {
|
||||
MatrixEvent,
|
||||
type Room,
|
||||
@@ -1468,7 +1468,7 @@ describe("DeviceListener", () => {
|
||||
});
|
||||
});
|
||||
|
||||
function mockKeyBackupFromServer(client: MockedObject<MatrixClient>, enabled: boolean) {
|
||||
function mockKeyBackupFromServer(client: Mocked<MatrixClient>, enabled: boolean) {
|
||||
client.getAccountDataFromServer.mockImplementation(async (eventType: string) => {
|
||||
switch (eventType) {
|
||||
case ACCOUNT_DATA_KEY_M_KEY_BACKUP:
|
||||
|
||||
@@ -11,7 +11,7 @@ import { logger } from "matrix-js-sdk/src/logger";
|
||||
import * as MatrixJs from "matrix-js-sdk/src/matrix";
|
||||
import { decodeBase64, encodeUnpaddedBase64 } from "matrix-js-sdk/src/matrix";
|
||||
import * as encryptAESSecretStorageItemModule from "matrix-js-sdk/src/utils/encryptAESSecretStorageItem";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import StorageEvictedDialog from "../../src/components/views/dialogs/StorageEvictedDialog";
|
||||
|
||||
@@ -5,7 +5,7 @@ Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import {
|
||||
ClientEvent,
|
||||
type MatrixClient,
|
||||
@@ -602,7 +602,7 @@ describe("Notifier", () => {
|
||||
slotDescription: { application: "m.call", id: "" },
|
||||
} as unknown as MatrixRTCSession;
|
||||
|
||||
mockClient.matrixRTC.getRoomSession.mockReturnValue(mockRtcSession);
|
||||
mocked(mockClient.matrixRTC.getRoomSession).mockReturnValue(mockRtcSession);
|
||||
|
||||
emitCallNotificationEvent();
|
||||
expect(ToastStore.sharedInstance().addOrReplaceToast).not.toHaveBeenCalled();
|
||||
|
||||
@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import "fake-indexeddb/auto";
|
||||
import React, { type ComponentProps, createRef, type RefObject } from "react";
|
||||
import { fireEvent, render, type RenderResult, screen, waitFor, within, act } from "jest-matrix-react";
|
||||
import { type Mocked, mocked } from "jest-mock";
|
||||
import { type Mocked, mocked } from "jest-mock-vitest-adapter";
|
||||
import { ClientEvent, type MatrixClient, MatrixEvent, Room, SyncState } from "matrix-js-sdk/src/matrix";
|
||||
import { type MediaHandler } from "matrix-js-sdk/src/webrtc/mediaHandler";
|
||||
import * as MatrixJs from "matrix-js-sdk/src/matrix";
|
||||
|
||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen, waitForElementToBeRemoved } from "jest-matrix-react";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { DELEGATED_OIDC_COMPATIBILITY, IdentityProviderBrand, type OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React from "react";
|
||||
import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved } from "jest-matrix-react";
|
||||
import { createClient, type MatrixClient, MatrixError, type OidcClientConfig } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import SdkConfig, { DEFAULTS } from "../../../../../src/SdkConfig";
|
||||
|
||||
@@ -12,7 +12,7 @@ import userEvent from "@testing-library/user-event";
|
||||
import { type MatrixClient, MatrixError, Room, RoomType } from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import { mocked, type Mocked } from "jest-mock";
|
||||
import { mocked, type Mocked } from "jest-mock-vitest-adapter";
|
||||
import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api";
|
||||
|
||||
import InviteDialog from "../../../../../src/components/views/dialogs/InviteDialog";
|
||||
|
||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import { Device, DeviceVerification, type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { type CryptoApi, DeviceVerificationStatus, type KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
|
||||
import { fireEvent, render, type RenderResult, screen, waitFor } from "jest-matrix-react";
|
||||
|
||||
@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React, { type ReactElement } from "react";
|
||||
import { render, screen, waitFor } from "jest-matrix-react";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import { ClientEvent, MatrixEvent, type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import SettingsStore, { type CallbackFn } from "../../../../../src/settings/SettingsStore";
|
||||
@@ -258,7 +258,7 @@ describe("<UserSettingsDialog />", () => {
|
||||
it("displays an indicator when user needs to set up recovery", async () => {
|
||||
// Initially, the user doesn't have secret storage, so it should display
|
||||
// an indicator.
|
||||
mockClient.secretStorage.getDefaultKeyId.mockResolvedValue(null);
|
||||
mocked(mockClient.secretStorage.getDefaultKeyId).mockResolvedValue(null);
|
||||
|
||||
const { container } = render(getComponent());
|
||||
|
||||
@@ -271,7 +271,7 @@ describe("<UserSettingsDialog />", () => {
|
||||
|
||||
// The user now has secret storage. Trigger an update and check that
|
||||
// the indicator disappears.
|
||||
mockClient.secretStorage.getDefaultKeyId.mockResolvedValue("foo");
|
||||
mocked(mockClient.secretStorage.getDefaultKeyId).mockResolvedValue("foo");
|
||||
mockClient.emit(ClientEvent.AccountData, new MatrixEvent({ type: "m.secret_storage.default_key" }));
|
||||
|
||||
await waitFor(() => {
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
import React, { act } from "react";
|
||||
import { render } from "jest-matrix-react";
|
||||
import { type CryptoApi } from "matrix-js-sdk/src/crypto-api";
|
||||
import { type Mocked } from "jest-mock";
|
||||
import { type Mocked } from "jest-mock-vitest-adapter";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { getMockClientWithEventEmitter } from "../../../../../test-utils";
|
||||
|
||||
@@ -10,7 +10,7 @@ import React from "react";
|
||||
import { EventType, getHttpUriForMxc, type IContent, type MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { fireEvent, render, screen } from "jest-matrix-react";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
import { type MockedObject } from "jest-mock";
|
||||
import { type MockedObject } from "jest-mock-vitest-adapter";
|
||||
|
||||
import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
|
||||
import { type RoomPermalinkCreator } from "../../../../../src/utils/permalinks/Permalinks";
|
||||
|
||||
@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React, { type ComponentProps } from "react";
|
||||
import { type MatrixClient, type MatrixEvent, PushRuleKind, type Room } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import { act, render, waitFor } from "jest-matrix-react";
|
||||
import { PushProcessor } from "matrix-js-sdk/src/pushprocessor";
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ import React from "react";
|
||||
import { type MatrixClient, ThreepidMedium } from "matrix-js-sdk/src/matrix";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { type MockedObject } from "jest-mock";
|
||||
import { type MockedObject } from "jest-mock-vitest-adapter";
|
||||
|
||||
import AccountUserSettingsTab from "../../../../../../../src/components/views/settings/tabs/user/AccountUserSettingsTab";
|
||||
import { SdkContextClass, SDKContext } from "../../../../../../../src/contexts/SDKContext";
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import {
|
||||
} from "../../../../../../test-utils";
|
||||
import MatrixClientBackedController from "../../../../../../../src/settings/controllers/MatrixClientBackedController";
|
||||
import MatrixClientBackedSettingsHandler from "../../../../../../../src/settings/handlers/MatrixClientBackedSettingsHandler";
|
||||
import type { MockedObject } from "jest-mock";
|
||||
import type { MockedObject } from "jest-mock-vitest-adapter";
|
||||
import {
|
||||
MEDIA_PREVIEW_ACCOUNT_DATA_TYPE,
|
||||
type MediaPreviewConfig,
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ import {
|
||||
MatrixError,
|
||||
type MatrixClient,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { mocked, type MockedObject } from "jest-mock";
|
||||
import { mocked, type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import fetchMock from "@fetch-mock/jest";
|
||||
|
||||
import {
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
Visibility,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { type MockedObject } from "jest-mock";
|
||||
import { type MockedObject } from "jest-mock-vitest-adapter";
|
||||
|
||||
import * as createRoomModule from "../../../../../src/createRoom";
|
||||
import SpaceCreateMenu, { createSpace } from "../../../../../src/components/views/spaces/SpaceCreateMenu";
|
||||
|
||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { type ComponentProps } from "react";
|
||||
import { mocked, type Mocked } from "jest-mock";
|
||||
import { mocked, type Mocked } from "jest-mock-vitest-adapter";
|
||||
import { render, type RenderResult } from "jest-matrix-react";
|
||||
import { TypedEventEmitter, type IMyDevice, type MatrixClient, Device } from "matrix-js-sdk/src/matrix";
|
||||
import { type VerificationRequest, VerificationRequestEvent } from "matrix-js-sdk/src/crypto-api";
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import defaultDispatcher from "../../../src/dispatcher/dispatcher";
|
||||
import { Action } from "../../../src/dispatcher/actions";
|
||||
import { AsyncActionPayload } from "../../../src/dispatcher/payloads";
|
||||
|
||||
describe("MatrixDispatcher", () => {
|
||||
it("should throw error if unregistering unknown token", () => {
|
||||
expect(() => defaultDispatcher.unregister("not-a-real-token")).toThrow(
|
||||
"Dispatcher.unregister(...): 'not-a-real-token' does not map to a registered callback.",
|
||||
);
|
||||
});
|
||||
|
||||
it("should execute callbacks in registered order", async () => {
|
||||
const deferred1 = Promise.withResolvers<number>();
|
||||
const deferred2 = Promise.withResolvers<number>();
|
||||
|
||||
const fn1 = jest.fn(() => deferred1.resolve(1));
|
||||
const fn2 = jest.fn(() => deferred2.resolve(2));
|
||||
|
||||
defaultDispatcher.register(fn1);
|
||||
defaultDispatcher.register(fn2);
|
||||
|
||||
defaultDispatcher.dispatch({ action: Action.OnLoggedIn });
|
||||
const res = await Promise.race([deferred1.promise, deferred2.promise]);
|
||||
|
||||
expect(res).toBe(1);
|
||||
});
|
||||
|
||||
it("should skip the queue for the given callback", async () => {
|
||||
const deferred1 = Promise.withResolvers<number>();
|
||||
const deferred2 = Promise.withResolvers<number>();
|
||||
|
||||
const fn1 = jest.fn(() => deferred1.resolve(1));
|
||||
const fn2 = jest.fn(() => deferred2.resolve(2));
|
||||
|
||||
defaultDispatcher.register(() => {
|
||||
defaultDispatcher.waitFor([id2]);
|
||||
});
|
||||
defaultDispatcher.register(fn1);
|
||||
const id2 = defaultDispatcher.register(fn2);
|
||||
|
||||
defaultDispatcher.dispatch({ action: Action.OnLoggedIn });
|
||||
const res = await Promise.race([deferred1.promise, deferred2.promise]);
|
||||
|
||||
expect(res).toBe(2);
|
||||
});
|
||||
|
||||
it("should not fire callback which was added during a dispatch", () => {
|
||||
const fn2 = jest.fn();
|
||||
|
||||
defaultDispatcher.register(() => {
|
||||
defaultDispatcher.register(fn2);
|
||||
});
|
||||
|
||||
defaultDispatcher.dispatch({ action: Action.OnLoggedIn }, true);
|
||||
|
||||
expect(fn2).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should handle AsyncActionPayload", () => {
|
||||
const fn = jest.fn();
|
||||
defaultDispatcher.register(fn);
|
||||
|
||||
const readyFn = jest.fn((dispatch) => {
|
||||
dispatch({ action: "test" });
|
||||
});
|
||||
defaultDispatcher.dispatch(new AsyncActionPayload(readyFn), true);
|
||||
|
||||
expect(fn).toHaveBeenLastCalledWith(expect.objectContaining({ action: "test" }));
|
||||
});
|
||||
});
|
||||
@@ -1,186 +0,0 @@
|
||||
/*
|
||||
Copyright 2025 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { type Mocked } from "jest-mock";
|
||||
import {
|
||||
Direction,
|
||||
type MatrixClient,
|
||||
type IEvent,
|
||||
MatrixEvent,
|
||||
type Room,
|
||||
ClientEvent,
|
||||
SyncState,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import EventIndex from "../../../src/indexing/EventIndex.ts";
|
||||
import { emitPromise, getMockClientWithEventEmitter, mockClientMethodsRooms, mockPlatformPeg } from "../../test-utils";
|
||||
import type BaseEventIndexManager from "../../../src/indexing/BaseEventIndexManager.ts";
|
||||
import { type ICrawlerCheckpoint } from "../../../src/indexing/BaseEventIndexManager.ts";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore.ts";
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe("EventIndex", () => {
|
||||
it("crawls through the loaded checkpoints", async () => {
|
||||
const mockIndexingManager = {
|
||||
loadCheckpoints: jest.fn(),
|
||||
removeCrawlerCheckpoint: jest.fn(),
|
||||
isEventIndexEmpty: jest.fn().mockResolvedValue(false),
|
||||
} as any as Mocked<BaseEventIndexManager>;
|
||||
mockPlatformPeg({ getEventIndexingManager: () => mockIndexingManager });
|
||||
|
||||
const room1 = { roomId: "!room1:id" } as any as Room;
|
||||
const room2 = { roomId: "!room2:id" } as any as Room;
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
getEventMapper: () => (obj: Partial<IEvent>) => new MatrixEvent(obj),
|
||||
createMessagesRequest: jest.fn(),
|
||||
...mockClientMethodsRooms([room1, room2]),
|
||||
});
|
||||
|
||||
jest.spyOn(SettingsStore, "getValueAt").mockImplementation((_level, settingName): any => {
|
||||
if (settingName === "crawlerSleepTime") return 0;
|
||||
return undefined;
|
||||
});
|
||||
|
||||
mockIndexingManager.loadCheckpoints.mockResolvedValue([
|
||||
{ roomId: "!room1:id", token: "token1", direction: Direction.Backward } as ICrawlerCheckpoint,
|
||||
{ roomId: "!room2:id", token: "token2", direction: Direction.Forward } as ICrawlerCheckpoint,
|
||||
]);
|
||||
|
||||
const indexer = new EventIndex();
|
||||
await indexer.init();
|
||||
let changedCheckpointPromise = emitPromise(indexer, "changedCheckpoint") as Promise<Room>;
|
||||
|
||||
indexer.startCrawler();
|
||||
|
||||
// Mock out the /messags request, and wait for the crawler to hit the first room
|
||||
const mock1 = mockCreateMessagesRequest(mockClient);
|
||||
let changedCheckpoint = await changedCheckpointPromise;
|
||||
expect(changedCheckpoint.roomId).toEqual("!room1:id");
|
||||
|
||||
await mock1.called;
|
||||
expect(mockClient.createMessagesRequest).toHaveBeenCalledWith("!room1:id", "token1", 100, "b");
|
||||
|
||||
// Continue, and wait for the crawler to hit the second room
|
||||
changedCheckpointPromise = emitPromise(indexer, "changedCheckpoint") as Promise<Room>;
|
||||
mock1.resolve({ chunk: [] });
|
||||
changedCheckpoint = await changedCheckpointPromise;
|
||||
expect(changedCheckpoint.roomId).toEqual("!room2:id");
|
||||
|
||||
// Mock out the /messages request again, and wait for it to be called
|
||||
const mock2 = mockCreateMessagesRequest(mockClient);
|
||||
await mock2.called;
|
||||
expect(mockClient.createMessagesRequest).toHaveBeenCalledWith("!room2:id", "token2", 100, "f");
|
||||
});
|
||||
|
||||
it("adds checkpoints for the encrypted rooms after the first sync", async () => {
|
||||
const mockIndexingManager = {
|
||||
loadCheckpoints: jest.fn().mockResolvedValue([]),
|
||||
isEventIndexEmpty: jest.fn().mockResolvedValue(true),
|
||||
addCrawlerCheckpoint: jest.fn(),
|
||||
removeCrawlerCheckpoint: jest.fn(),
|
||||
commitLiveEvents: jest.fn(),
|
||||
} as any as Mocked<BaseEventIndexManager>;
|
||||
mockPlatformPeg({ getEventIndexingManager: () => mockIndexingManager });
|
||||
|
||||
const room1 = {
|
||||
roomId: "!room1:id",
|
||||
getLiveTimeline: () => ({
|
||||
getPaginationToken: () => "token1",
|
||||
}),
|
||||
} as any as Room;
|
||||
const room2 = {
|
||||
roomId: "!room2:id",
|
||||
getLiveTimeline: () => ({
|
||||
getPaginationToken: () => "token2",
|
||||
}),
|
||||
} as any as Room;
|
||||
const mockCrypto = {
|
||||
isEncryptionEnabledInRoom: jest.fn().mockResolvedValue(true),
|
||||
};
|
||||
const mockClient = getMockClientWithEventEmitter({
|
||||
getEventMapper: () => (obj: Partial<IEvent>) => new MatrixEvent(obj),
|
||||
createMessagesRequest: jest.fn(),
|
||||
getCrypto: () => mockCrypto as any,
|
||||
...mockClientMethodsRooms([room1, room2]),
|
||||
});
|
||||
|
||||
const commitLiveEventsCalled = Promise.withResolvers<void>();
|
||||
mockIndexingManager.commitLiveEvents.mockImplementation(async () => {
|
||||
commitLiveEventsCalled.resolve();
|
||||
});
|
||||
|
||||
const indexer = new EventIndex();
|
||||
await indexer.init();
|
||||
|
||||
// During the first sync, some events are added to the index, meaning that `isEventIndexEmpty` will now be false.
|
||||
mockIndexingManager.isEventIndexEmpty.mockResolvedValue(false);
|
||||
|
||||
// The first sync completes:
|
||||
mockClient.emit(ClientEvent.Sync, SyncState.Syncing, null, {});
|
||||
|
||||
// Wait for `commitLiveEvents` to be called, by which time the checkpoints should have been added.
|
||||
await commitLiveEventsCalled.promise;
|
||||
expect(mockIndexingManager.addCrawlerCheckpoint).toHaveBeenCalledTimes(4);
|
||||
expect(mockIndexingManager.addCrawlerCheckpoint).toHaveBeenCalledWith({
|
||||
roomId: "!room1:id",
|
||||
token: "token1",
|
||||
direction: Direction.Backward,
|
||||
fullCrawl: true,
|
||||
});
|
||||
expect(mockIndexingManager.addCrawlerCheckpoint).toHaveBeenCalledWith({
|
||||
roomId: "!room1:id",
|
||||
token: "token1",
|
||||
direction: Direction.Forward,
|
||||
});
|
||||
expect(mockIndexingManager.addCrawlerCheckpoint).toHaveBeenCalledWith({
|
||||
roomId: "!room2:id",
|
||||
token: "token2",
|
||||
direction: Direction.Backward,
|
||||
fullCrawl: true,
|
||||
});
|
||||
expect(mockIndexingManager.addCrawlerCheckpoint).toHaveBeenCalledWith({
|
||||
roomId: "!room2:id",
|
||||
token: "token2",
|
||||
direction: Direction.Forward,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Mock out the `createMessagesRequest` method on the client, with an implementation that will block until a resolver is called.
|
||||
*
|
||||
* @returns An object with the following properties:
|
||||
* * `called`: A promise that resolves when `createMessagesRequest` is called.
|
||||
* * `resolve`: A function that can be called to allow `createMessagesRequest` to complete.
|
||||
*/
|
||||
function mockCreateMessagesRequest(mockClient: Mocked<MatrixClient>): {
|
||||
called: Promise<void>;
|
||||
resolve: (result: any) => void;
|
||||
} {
|
||||
const messagesCalledPromise = Promise.withResolvers<void>();
|
||||
const messagesResultPromise = Promise.withResolvers();
|
||||
mockClient.createMessagesRequest.mockImplementationOnce(() => {
|
||||
messagesCalledPromise.resolve();
|
||||
return messagesResultPromise.promise as any;
|
||||
});
|
||||
return {
|
||||
called: messagesCalledPromise.promise,
|
||||
resolve: messagesResultPromise.resolve,
|
||||
};
|
||||
}
|
||||
@@ -13,7 +13,7 @@ import { DialogContent, type DialogProps } from "@matrix-org/react-sdk-module-ap
|
||||
import { screen, within } from "jest-matrix-react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { type Mocked } from "jest-mock";
|
||||
import { type Mocked } from "jest-mock-vitest-adapter";
|
||||
|
||||
import { ProxiedModuleApi } from "../../../src/modules/ProxiedModuleApi";
|
||||
import { getMockClientWithEventEmitter, mkRoom, stubClient } from "../../test-utils";
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
Copyright 2024, 2025 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { ClientEvent, type MatrixClient, type Room, SyncState } from "matrix-js-sdk/src/matrix";
|
||||
import { waitFor } from "jest-matrix-react";
|
||||
|
||||
import type BasePlatform from "../../../src/BasePlatform";
|
||||
import SdkConfig from "../../../src/SdkConfig";
|
||||
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
import { mkStubRoom, mockPlatformPeg, stubClient } from "../../test-utils";
|
||||
import { SETTINGS, type SettingKey } from "../../../src/settings/Settings.tsx";
|
||||
import MatrixClientBackedController from "../../../src/settings/controllers/MatrixClientBackedController.ts";
|
||||
|
||||
const TEST_DATA = [
|
||||
{
|
||||
name: "Electron.showTrayIcon" as SettingKey,
|
||||
level: SettingLevel.PLATFORM,
|
||||
value: true,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* An existing setting that has {@link IBaseSetting#supportedLevelsAreOrdered} set to true.
|
||||
*/
|
||||
const SETTING_NAME_WITH_CONFIG_OVERRIDE = "feature_msc3531_hide_messages_pending_moderation";
|
||||
|
||||
describe("SettingsStore", () => {
|
||||
let platformSettings: Record<string, any>;
|
||||
|
||||
beforeAll(() => {
|
||||
jest.clearAllMocks();
|
||||
platformSettings = {};
|
||||
mockPlatformPeg({
|
||||
isLevelSupported: jest.fn().mockReturnValue(true),
|
||||
supportsSetting: jest.fn().mockReturnValue(true),
|
||||
setSettingValue: jest.fn().mockImplementation((settingName: string, value: any) => {
|
||||
platformSettings[settingName] = value;
|
||||
}),
|
||||
getSettingValue: jest.fn().mockImplementation((settingName: string) => {
|
||||
return platformSettings[settingName];
|
||||
}),
|
||||
reload: jest.fn(),
|
||||
} as unknown as BasePlatform);
|
||||
|
||||
TEST_DATA.forEach((d) => {
|
||||
SettingsStore.setValue(d.name, null, d.level, d.value);
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
SdkConfig.reset();
|
||||
SettingsStore.reset();
|
||||
});
|
||||
|
||||
describe("getValueAt", () => {
|
||||
TEST_DATA.forEach((d) => {
|
||||
it(`should return the value "${d.level}"."${d.name}"`, () => {
|
||||
expect(SettingsStore.getValueAt(d.level, d.name)).toBe(d.value);
|
||||
// regression test #22545
|
||||
expect(SettingsStore.getValueAt(d.level, d.name)).toBe(d.value);
|
||||
});
|
||||
});
|
||||
|
||||
it(`supportedLevelsAreOrdered correctly overrides setting`, async () => {
|
||||
SdkConfig.put({
|
||||
features: {
|
||||
[SETTING_NAME_WITH_CONFIG_OVERRIDE]: false,
|
||||
},
|
||||
});
|
||||
await SettingsStore.setValue(SETTING_NAME_WITH_CONFIG_OVERRIDE, null, SettingLevel.DEVICE, true);
|
||||
expect(SettingsStore.getValue(SETTING_NAME_WITH_CONFIG_OVERRIDE)).toBe(false);
|
||||
});
|
||||
|
||||
it(`supportedLevelsAreOrdered doesn't incorrectly override setting`, async () => {
|
||||
await SettingsStore.setValue(SETTING_NAME_WITH_CONFIG_OVERRIDE, null, SettingLevel.DEVICE, true);
|
||||
expect(SettingsStore.getValueAt(SettingLevel.DEVICE, SETTING_NAME_WITH_CONFIG_OVERRIDE)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("exportForRageshake", () => {
|
||||
it("should not export settings marked as non-exportable", async () => {
|
||||
await SettingsStore.setValue("userTimezone", null, SettingLevel.DEVICE, "Europe/London");
|
||||
const values = JSON.parse(SettingsStore.exportForRageshake()) as Record<SettingKey, unknown>;
|
||||
for (const exportedKey of Object.keys(values) as SettingKey[]) {
|
||||
expect(SETTINGS[exportedKey].shouldExportToRageshake).not.toEqual(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("runMigrations", () => {
|
||||
let client: MatrixClient;
|
||||
let room: Room;
|
||||
|
||||
beforeEach(() => {
|
||||
client = stubClient();
|
||||
room = mkStubRoom("!room:example.org", "Room", client);
|
||||
client.getRooms = jest.fn().mockReturnValue([room]);
|
||||
client.getRoom = jest.fn().mockReturnValue(room);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
describe("Migrate media preview configuration", () => {
|
||||
beforeEach(() => {
|
||||
MatrixClientBackedController.matrixClient = client;
|
||||
client.getAccountData = jest.fn().mockImplementation((type) => {
|
||||
if (type === "im.vector.web.settings") {
|
||||
return {
|
||||
getContent: jest.fn().mockReturnValue({
|
||||
showImages: false,
|
||||
showAvatarsOnInvites: false,
|
||||
}),
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("migrates media preview configuration immediately", async () => {
|
||||
client.setAccountData = jest.fn();
|
||||
SettingsStore.runMigrations(false);
|
||||
expect(client.setAccountData).toHaveBeenCalledWith("io.element.msc4278.media_preview_config", {
|
||||
invite_avatars: "off",
|
||||
media_previews: "off",
|
||||
});
|
||||
});
|
||||
it("migrates media preview configuration once client is ready", async () => {
|
||||
client.setAccountData = jest.fn();
|
||||
const mockInitialSync = (client.isInitialSyncComplete = jest.fn().mockReturnValue(false));
|
||||
SettingsStore.runMigrations(false);
|
||||
mockInitialSync.mockReturnValue(true);
|
||||
client.emit(ClientEvent.Sync, SyncState.Prepared, null);
|
||||
// Update is asynchronous
|
||||
waitFor(() => {
|
||||
expect(client.setAccountData).toHaveBeenCalledWith("io.element.msc4278.media_preview_config", {
|
||||
invite_avatars: "off",
|
||||
media_previews: "off",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("does not migrate media preview configuration if the session is fresh", async () => {
|
||||
client.setAccountData = jest.fn();
|
||||
SettingsStore.runMigrations(true);
|
||||
client.emit(ClientEvent.Sync, SyncState.Prepared, null);
|
||||
expect(client.setAccountData).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not migrate media preview configuration if the account data is already set", async () => {
|
||||
client.setAccountData = jest.fn();
|
||||
client.getAccountData = jest.fn().mockReturnValue({});
|
||||
SettingsStore.runMigrations(false);
|
||||
client.emit(ClientEvent.Sync, SyncState.Prepared, null);
|
||||
expect(client.setAccountData).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { ImageSize, suggestedSize } from "../../../../src/settings/enums/ImageSize";
|
||||
|
||||
describe("ImageSize", () => {
|
||||
describe("suggestedSize", () => {
|
||||
it("constrains width", () => {
|
||||
const size = suggestedSize(ImageSize.Normal, { w: 648, h: 162 });
|
||||
expect(size).toStrictEqual({ w: 324, h: 81 });
|
||||
});
|
||||
it("constrains height", () => {
|
||||
const size = suggestedSize(ImageSize.Normal, { w: 162, h: 648 });
|
||||
expect(size).toStrictEqual({ w: 81, h: 324 });
|
||||
});
|
||||
it("constrains width in large mode", () => {
|
||||
const size = suggestedSize(ImageSize.Large, { w: 2400, h: 1200 });
|
||||
expect(size).toStrictEqual({ w: 800, h: 400 });
|
||||
});
|
||||
it("returns max values if content size is not specified", () => {
|
||||
const size = suggestedSize(ImageSize.Normal, {});
|
||||
expect(size).toStrictEqual({ w: 324, h: 324 });
|
||||
});
|
||||
it("returns integer values", () => {
|
||||
const size = suggestedSize(ImageSize.Normal, { w: 642, h: 350 }); // does not divide evenly
|
||||
expect(size).toStrictEqual({ w: 324, h: 176 });
|
||||
});
|
||||
it("returns integer values for portrait images", () => {
|
||||
const size = suggestedSize(ImageSize.Normal, { w: 720, h: 1280 });
|
||||
expect(size).toStrictEqual({ w: 182, h: 324 });
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import SettingsStore from "../../../../src/settings/SettingsStore";
|
||||
import ThemeWatcher from "../../../../src/settings/watchers/ThemeWatcher";
|
||||
import { type SettingLevel } from "../../../../src/settings/SettingLevel";
|
||||
import { type SettingKey, type Settings } from "../../../../src/settings/Settings.tsx";
|
||||
|
||||
function makeMatchMedia(values: any) {
|
||||
class FakeMediaQueryList {
|
||||
matches: false;
|
||||
media?: null;
|
||||
onchange?: null;
|
||||
addListener() {}
|
||||
removeListener() {}
|
||||
addEventListener() {}
|
||||
removeEventListener() {}
|
||||
dispatchEvent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
constructor(query: string) {
|
||||
this.matches = values[query];
|
||||
}
|
||||
}
|
||||
|
||||
return function matchMedia(query: string) {
|
||||
return new FakeMediaQueryList(query) as unknown as MediaQueryList;
|
||||
};
|
||||
}
|
||||
|
||||
function makeGetValue(values: any): any {
|
||||
return function getValue<S extends SettingKey>(
|
||||
settingName: S,
|
||||
_roomId: string | null = null,
|
||||
_excludeDefault = false,
|
||||
): Settings[S] {
|
||||
return values[settingName];
|
||||
};
|
||||
}
|
||||
|
||||
function makeGetValueAt(values: any) {
|
||||
return function getValueAt(
|
||||
_level: SettingLevel,
|
||||
settingName: string,
|
||||
_roomId: string | null = null,
|
||||
_explicit = false,
|
||||
_excludeDefault = false,
|
||||
): any {
|
||||
return values[settingName];
|
||||
};
|
||||
}
|
||||
|
||||
describe("ThemeWatcher", function () {
|
||||
it("should choose a light theme by default", () => {
|
||||
// Given no system settings
|
||||
global.matchMedia = makeMatchMedia({});
|
||||
|
||||
// Then getEffectiveTheme returns light
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("light");
|
||||
});
|
||||
|
||||
it("should choose default theme if system settings are inconclusive", () => {
|
||||
// Given no system settings but we asked to use them
|
||||
global.matchMedia = makeMatchMedia({});
|
||||
SettingsStore.getValue = makeGetValue({
|
||||
use_system_theme: true,
|
||||
theme: "light",
|
||||
});
|
||||
|
||||
// Then getEffectiveTheme returns light
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("light");
|
||||
});
|
||||
|
||||
it("should choose a dark theme if that is selected", () => {
|
||||
// Given system says light high contrast but theme is set to dark
|
||||
global.matchMedia = makeMatchMedia({
|
||||
"(prefers-contrast: more)": true,
|
||||
"(prefers-color-scheme: light)": true,
|
||||
});
|
||||
SettingsStore.getValueAt = makeGetValueAt({ theme: "dark" });
|
||||
|
||||
// Then getEffectiveTheme returns dark
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("dark");
|
||||
});
|
||||
|
||||
it("should choose a light theme if that is selected", () => {
|
||||
// Given system settings say dark high contrast but theme set to light
|
||||
global.matchMedia = makeMatchMedia({
|
||||
"(prefers-contrast: more)": true,
|
||||
"(prefers-color-scheme: dark)": true,
|
||||
});
|
||||
SettingsStore.getValueAt = makeGetValueAt({ theme: "light" });
|
||||
|
||||
// Then getEffectiveTheme returns light
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("light");
|
||||
});
|
||||
|
||||
it("should choose a light-high-contrast theme if that is selected", () => {
|
||||
// Given system settings say dark and theme set to light-high-contrast
|
||||
global.matchMedia = makeMatchMedia({ "(prefers-color-scheme: dark)": true });
|
||||
SettingsStore.getValueAt = makeGetValueAt({ theme: "light-high-contrast" });
|
||||
|
||||
// Then getEffectiveTheme returns light-high-contrast
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("light-high-contrast");
|
||||
});
|
||||
|
||||
it("should choose a light theme if system prefers it (via default)", () => {
|
||||
// Given system prefers lightness, even though we did not
|
||||
// click "Use system theme" or choose a theme explicitly
|
||||
global.matchMedia = makeMatchMedia({ "(prefers-color-scheme: light)": true });
|
||||
SettingsStore.getValueAt = makeGetValueAt({});
|
||||
SettingsStore.getValue = makeGetValue({ use_system_theme: true });
|
||||
|
||||
// Then getEffectiveTheme returns light
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("light");
|
||||
});
|
||||
|
||||
it("should choose a dark theme if system prefers it (via default)", () => {
|
||||
// Given system prefers darkness, even though we did not
|
||||
// click "Use system theme" or choose a theme explicitly
|
||||
global.matchMedia = makeMatchMedia({ "(prefers-color-scheme: dark)": true });
|
||||
SettingsStore.getValueAt = makeGetValueAt({});
|
||||
SettingsStore.getValue = makeGetValue({ use_system_theme: true });
|
||||
|
||||
// Then getEffectiveTheme returns dark
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("dark");
|
||||
});
|
||||
|
||||
it("should choose a light theme if system prefers it (explicit)", () => {
|
||||
// Given system prefers lightness
|
||||
global.matchMedia = makeMatchMedia({ "(prefers-color-scheme: light)": true });
|
||||
SettingsStore.getValueAt = makeGetValueAt({ use_system_theme: true });
|
||||
SettingsStore.getValue = makeGetValue({ use_system_theme: true });
|
||||
|
||||
// Then getEffectiveTheme returns light
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("light");
|
||||
});
|
||||
|
||||
it("should choose a dark theme if system prefers it (explicit)", () => {
|
||||
// Given system prefers darkness
|
||||
global.matchMedia = makeMatchMedia({ "(prefers-color-scheme: dark)": true });
|
||||
SettingsStore.getValueAt = makeGetValueAt({ use_system_theme: true });
|
||||
SettingsStore.getValue = makeGetValue({ use_system_theme: true });
|
||||
|
||||
// Then getEffectiveTheme returns dark
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("dark");
|
||||
});
|
||||
|
||||
it("should choose a high-contrast theme if system prefers it", () => {
|
||||
// Given system prefers high contrast and light
|
||||
global.matchMedia = makeMatchMedia({
|
||||
"(prefers-contrast: more)": true,
|
||||
"(prefers-color-scheme: light)": true,
|
||||
});
|
||||
SettingsStore.getValueAt = makeGetValueAt({ use_system_theme: true });
|
||||
SettingsStore.getValue = makeGetValue({ use_system_theme: true });
|
||||
|
||||
// Then getEffectiveTheme returns light-high-contrast
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("light-high-contrast");
|
||||
});
|
||||
|
||||
it("should not choose a high-contrast theme if not available", () => {
|
||||
// Given system prefers high contrast and dark, but we don't (yet)
|
||||
// have a high-contrast dark theme
|
||||
global.matchMedia = makeMatchMedia({
|
||||
"(prefers-contrast: more)": true,
|
||||
"(prefers-color-scheme: dark)": true,
|
||||
});
|
||||
SettingsStore.getValueAt = makeGetValueAt({ use_system_theme: true });
|
||||
SettingsStore.getValue = makeGetValue({ use_system_theme: true });
|
||||
|
||||
// Then getEffectiveTheme returns dark
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("dark");
|
||||
});
|
||||
|
||||
it("should identify custom dark themes as dark", () => {
|
||||
SettingsStore.getValueAt = makeGetValueAt({ use_system_theme: false, theme: "custom-darkula" });
|
||||
SettingsStore.getValue = makeGetValue({
|
||||
custom_themes: [
|
||||
{
|
||||
name: "darkula",
|
||||
is_dark: true,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const themeWatcher = new ThemeWatcher();
|
||||
expect(themeWatcher.getEffectiveTheme()).toBe("custom-darkula");
|
||||
expect(themeWatcher.isUserOnDarkTheme()).toBe(true);
|
||||
});
|
||||
});
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { KnownMembership } from "matrix-js-sdk/src/types";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { type Mocked } from "jest-mock";
|
||||
import { type Mocked } from "jest-mock-vitest-adapter";
|
||||
|
||||
import { OwnBeaconStore, OwnBeaconStoreEvent } from "../../../src/stores/OwnBeaconStore";
|
||||
import {
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked } from "jest-mock";
|
||||
import { mocked } from "jest-mock-vitest-adapter";
|
||||
import { KnownMembership, MatrixError, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
import {
|
||||
@@ -181,7 +181,7 @@ describe("RoomViewStore", function () {
|
||||
jest.clearAllMocks();
|
||||
mockClient.credentials = { userId: userId };
|
||||
mockClient.joinRoom.mockResolvedValue(room);
|
||||
mockClient.getRoom.mockImplementation((roomId: string): Room | null => {
|
||||
mockClient.getRoom.mockImplementation((roomId?: string): Room | null => {
|
||||
if (roomId === room.roomId) return room;
|
||||
if (roomId === room2.roomId) return room2;
|
||||
return null;
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type Mocked, mocked } from "jest-mock";
|
||||
import { type Mocked, mocked } from "jest-mock-vitest-adapter";
|
||||
import {
|
||||
type HttpApiEvent,
|
||||
type HttpApiEventHandlerMap,
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
* Copyright 2024 The Matrix.org Foundation C.I.C.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { EventTimeline, EventType, type IEvent, type MatrixClient, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
import { createTestClient } from "../../test-utils";
|
||||
import PinningUtils from "../../../src/utils/PinningUtils";
|
||||
import SettingsStore from "../../../src/settings/SettingsStore";
|
||||
import { isContentActionable } from "../../../src/utils/EventUtils";
|
||||
import { ReadPinsEventId } from "../../../src/components/views/right_panel/types";
|
||||
|
||||
jest.mock("../../../src/utils/EventUtils", () => {
|
||||
return {
|
||||
isContentActionable: jest.fn(),
|
||||
canPinEvent: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
describe("PinningUtils", () => {
|
||||
const roomId = "!room:example.org";
|
||||
const userId = "@alice:example.org";
|
||||
|
||||
const mockedIsContentActionable = mocked(isContentActionable);
|
||||
|
||||
let matrixClient: MatrixClient;
|
||||
let room: Room;
|
||||
|
||||
/**
|
||||
* Create a pinned event with the given content.
|
||||
* @param content
|
||||
*/
|
||||
function makePinEvent(content?: Partial<IEvent>) {
|
||||
return new MatrixEvent({
|
||||
type: EventType.RoomMessage,
|
||||
sender: userId,
|
||||
content: {
|
||||
body: "First pinned message",
|
||||
msgtype: "m.text",
|
||||
},
|
||||
room_id: roomId,
|
||||
origin_server_ts: 0,
|
||||
event_id: "$eventId",
|
||||
...content,
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
// Enable feature pinning
|
||||
jest.spyOn(SettingsStore, "getValue").mockReturnValue(true);
|
||||
mockedIsContentActionable.mockImplementation(() => true);
|
||||
|
||||
matrixClient = createTestClient();
|
||||
room = new Room(roomId, matrixClient, userId);
|
||||
matrixClient.getRoom = jest.fn().mockReturnValue(room);
|
||||
|
||||
jest.spyOn(
|
||||
matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||
"mayClientSendStateEvent",
|
||||
).mockReturnValue(true);
|
||||
});
|
||||
|
||||
describe("isUnpinnable", () => {
|
||||
test.each(PinningUtils.PINNABLE_EVENT_TYPES)("should return true for pinnable event types", (eventType) => {
|
||||
const event = makePinEvent({ type: eventType });
|
||||
expect(PinningUtils.isUnpinnable(event)).toBe(true);
|
||||
});
|
||||
|
||||
test("should return false for a non pinnable event type", () => {
|
||||
const event = makePinEvent({ type: EventType.RoomCreate });
|
||||
expect(PinningUtils.isUnpinnable(event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return true for a redacted event", () => {
|
||||
const event = makePinEvent({ unsigned: { redacted_because: "because" as unknown as IEvent } });
|
||||
expect(PinningUtils.isUnpinnable(event)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isPinnable", () => {
|
||||
test.each(PinningUtils.PINNABLE_EVENT_TYPES)("should return true for pinnable event types", (eventType) => {
|
||||
const event = makePinEvent({ type: eventType });
|
||||
expect(PinningUtils.isPinnable(event)).toBe(true);
|
||||
});
|
||||
|
||||
test("should return false for a redacted event", () => {
|
||||
const event = makePinEvent({ unsigned: { redacted_because: "because" as unknown as IEvent } });
|
||||
expect(PinningUtils.isPinnable(event)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("isPinned", () => {
|
||||
test("should return false if no room", () => {
|
||||
matrixClient.getRoom = jest.fn().mockReturnValue(undefined);
|
||||
const event = makePinEvent();
|
||||
|
||||
expect(PinningUtils.isPinned(matrixClient, event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return false if no pinned event", () => {
|
||||
jest.spyOn(
|
||||
matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||
"getStateEvents",
|
||||
).mockReturnValue(null);
|
||||
|
||||
const event = makePinEvent();
|
||||
expect(PinningUtils.isPinned(matrixClient, event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return false if pinned events do not contain the event id", () => {
|
||||
jest.spyOn(
|
||||
matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||
"getStateEvents",
|
||||
).mockReturnValue({
|
||||
// @ts-ignore
|
||||
getContent: () => ({ pinned: ["$otherEventId"] }),
|
||||
});
|
||||
|
||||
const event = makePinEvent();
|
||||
expect(PinningUtils.isPinned(matrixClient, event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return true if pinned events contains the event id", () => {
|
||||
const event = makePinEvent();
|
||||
jest.spyOn(
|
||||
matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||
"getStateEvents",
|
||||
).mockReturnValue({
|
||||
// @ts-ignore
|
||||
getContent: () => ({ pinned: [event.getId()] }),
|
||||
});
|
||||
|
||||
expect(PinningUtils.isPinned(matrixClient, event)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("canPin & canUnpin", () => {
|
||||
describe("canPin", () => {
|
||||
test("should return false if event is not actionable", () => {
|
||||
mockedIsContentActionable.mockImplementation(() => false);
|
||||
const event = makePinEvent();
|
||||
|
||||
expect(PinningUtils.canPin(matrixClient, event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return false if no room", () => {
|
||||
matrixClient.getRoom = jest.fn().mockReturnValue(undefined);
|
||||
const event = makePinEvent();
|
||||
|
||||
expect(PinningUtils.canPin(matrixClient, event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return false if client cannot send state event", () => {
|
||||
jest.spyOn(
|
||||
matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||
"mayClientSendStateEvent",
|
||||
).mockReturnValue(false);
|
||||
const event = makePinEvent();
|
||||
|
||||
expect(PinningUtils.canPin(matrixClient, event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return false if event is not pinnable", () => {
|
||||
const event = makePinEvent({ type: EventType.RoomCreate });
|
||||
|
||||
expect(PinningUtils.canPin(matrixClient, event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return true if all conditions are met", () => {
|
||||
const event = makePinEvent();
|
||||
|
||||
expect(PinningUtils.canPin(matrixClient, event)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("canUnpin", () => {
|
||||
test("should return false if event is not unpinnable", () => {
|
||||
const event = makePinEvent({ type: EventType.RoomCreate });
|
||||
|
||||
expect(PinningUtils.canUnpin(matrixClient, event)).toBe(false);
|
||||
});
|
||||
|
||||
test("should return true if all conditions are met", () => {
|
||||
const event = makePinEvent();
|
||||
|
||||
expect(PinningUtils.canUnpin(matrixClient, event)).toBe(true);
|
||||
});
|
||||
|
||||
test("should return true if the event is redacted", () => {
|
||||
const event = makePinEvent({ unsigned: { redacted_because: "because" as unknown as IEvent } });
|
||||
|
||||
expect(PinningUtils.canUnpin(matrixClient, event)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("pinOrUnpinEvent", () => {
|
||||
test("should do nothing if no room", async () => {
|
||||
matrixClient.getRoom = jest.fn().mockReturnValue(undefined);
|
||||
const event = makePinEvent();
|
||||
|
||||
await PinningUtils.pinOrUnpinEvent(matrixClient, event);
|
||||
expect(matrixClient.sendStateEvent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("should do nothing if no event id", async () => {
|
||||
const event = makePinEvent({ event_id: undefined });
|
||||
|
||||
await PinningUtils.pinOrUnpinEvent(matrixClient, event);
|
||||
expect(matrixClient.sendStateEvent).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("should pin the event if not pinned", async () => {
|
||||
jest.spyOn(
|
||||
matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||
"getStateEvents",
|
||||
).mockReturnValue({
|
||||
// @ts-ignore
|
||||
getContent: () => ({ pinned: ["$otherEventId"] }),
|
||||
});
|
||||
|
||||
jest.spyOn(room, "getAccountData").mockReturnValue({
|
||||
getContent: jest.fn().mockReturnValue({
|
||||
event_ids: ["$otherEventId"],
|
||||
}),
|
||||
} as unknown as MatrixEvent);
|
||||
|
||||
const event = makePinEvent();
|
||||
await PinningUtils.pinOrUnpinEvent(matrixClient, event);
|
||||
|
||||
expect(matrixClient.setRoomAccountData).toHaveBeenCalledWith(roomId, ReadPinsEventId, {
|
||||
event_ids: ["$otherEventId", event.getId()],
|
||||
});
|
||||
expect(matrixClient.sendStateEvent).toHaveBeenCalledWith(
|
||||
roomId,
|
||||
EventType.RoomPinnedEvents,
|
||||
{ pinned: ["$otherEventId", event.getId()] },
|
||||
"",
|
||||
);
|
||||
});
|
||||
|
||||
test("should unpin the event if already pinned", async () => {
|
||||
const event = makePinEvent();
|
||||
|
||||
jest.spyOn(
|
||||
matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||
"getStateEvents",
|
||||
).mockReturnValue({
|
||||
// @ts-ignore
|
||||
getContent: () => ({ pinned: [event.getId(), "$otherEventId"] }),
|
||||
});
|
||||
|
||||
await PinningUtils.pinOrUnpinEvent(matrixClient, event);
|
||||
expect(matrixClient.sendStateEvent).toHaveBeenCalledWith(
|
||||
roomId,
|
||||
EventType.RoomPinnedEvents,
|
||||
{ pinned: ["$otherEventId"] },
|
||||
"",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("userHasPinOrUnpinPermission", () => {
|
||||
test("should return true if user can pin or unpin", () => {
|
||||
expect(PinningUtils.userHasPinOrUnpinPermission(matrixClient, room)).toBe(true);
|
||||
});
|
||||
|
||||
test("should return false if client cannot send state event", () => {
|
||||
jest.spyOn(
|
||||
matrixClient.getRoom(roomId)!.getLiveTimeline().getState(EventTimeline.FORWARDS)!,
|
||||
"mayClientSendStateEvent",
|
||||
).mockReturnValue(false);
|
||||
|
||||
expect(PinningUtils.userHasPinOrUnpinPermission(matrixClient, room)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("unpinAllEvents", () => {
|
||||
it("should unpin all events in the given room", async () => {
|
||||
await PinningUtils.unpinAllEvents(matrixClient, roomId);
|
||||
|
||||
expect(matrixClient.sendStateEvent).toHaveBeenCalledWith(
|
||||
roomId,
|
||||
EventType.RoomPinnedEvents,
|
||||
{ pinned: [] },
|
||||
"",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { Singleflight } from "../../../src/utils/Singleflight";
|
||||
|
||||
describe("Singleflight", () => {
|
||||
afterEach(() => {
|
||||
Singleflight.forgetAll();
|
||||
});
|
||||
|
||||
it("should throw for bad context variables", () => {
|
||||
const permutations: [object | null, string | null][] = [
|
||||
[null, null],
|
||||
[{}, null],
|
||||
[null, "test"],
|
||||
];
|
||||
for (const p of permutations) {
|
||||
expect(() => Singleflight.for(p[0], p[1])).toThrow("An instance and key must be supplied");
|
||||
}
|
||||
});
|
||||
|
||||
it("should execute the function once", () => {
|
||||
const instance = {};
|
||||
const key = "test";
|
||||
const val = {}; // unique object for reference check
|
||||
const fn = jest.fn().mockReturnValue(val);
|
||||
const sf = Singleflight.for(instance, key);
|
||||
const r1 = sf.do(fn);
|
||||
expect(r1).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
const r2 = sf.do(fn);
|
||||
expect(r2).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it("should execute the function once, even with new contexts", () => {
|
||||
const instance = {};
|
||||
const key = "test";
|
||||
const val = {}; // unique object for reference check
|
||||
const fn = jest.fn().mockReturnValue(val);
|
||||
let sf = Singleflight.for(instance, key);
|
||||
const r1 = sf.do(fn);
|
||||
expect(r1).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
sf = Singleflight.for(instance, key); // RESET FOR TEST
|
||||
const r2 = sf.do(fn);
|
||||
expect(r2).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
it("should execute the function twice if the result was forgotten", () => {
|
||||
const instance = {};
|
||||
const key = "test";
|
||||
const val = {}; // unique object for reference check
|
||||
const fn = jest.fn().mockReturnValue(val);
|
||||
const sf = Singleflight.for(instance, key);
|
||||
const r1 = sf.do(fn);
|
||||
expect(r1).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
sf.forget();
|
||||
const r2 = sf.do(fn);
|
||||
expect(r2).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(2);
|
||||
});
|
||||
|
||||
it("should execute the function twice if the instance was forgotten", () => {
|
||||
const instance = {};
|
||||
const key = "test";
|
||||
const val = {}; // unique object for reference check
|
||||
const fn = jest.fn().mockReturnValue(val);
|
||||
const sf = Singleflight.for(instance, key);
|
||||
const r1 = sf.do(fn);
|
||||
expect(r1).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
Singleflight.forgetAllFor(instance);
|
||||
const r2 = sf.do(fn);
|
||||
expect(r2).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(2);
|
||||
});
|
||||
|
||||
it("should execute the function twice if everything was forgotten", () => {
|
||||
const instance = {};
|
||||
const key = "test";
|
||||
const val = {}; // unique object for reference check
|
||||
const fn = jest.fn().mockReturnValue(val);
|
||||
const sf = Singleflight.for(instance, key);
|
||||
const r1 = sf.do(fn);
|
||||
expect(r1).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(1);
|
||||
Singleflight.forgetAll();
|
||||
const r2 = sf.do(fn);
|
||||
expect(r2).toBe(val);
|
||||
expect(fn.mock.calls.length).toBe(2);
|
||||
});
|
||||
});
|
||||
@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { type Mocked } from "jest-mock";
|
||||
import { type Mocked } from "jest-mock-vitest-adapter";
|
||||
|
||||
import {
|
||||
type GenericPosition,
|
||||
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { type Mocked, mocked } from "jest-mock";
|
||||
import { type Mocked, mocked } from "jest-mock-vitest-adapter";
|
||||
import { type Device, type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { getDeviceCryptoInfo, getUserDeviceIds } from "../../../../src/utils/crypto/deviceInfo";
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
Copyright 2026 Element Creations Ltd.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { onSubmitPreventDefault } from "../../../src/utils/form.ts";
|
||||
|
||||
describe("onSubmitPreventDefault", () => {
|
||||
it("should preventDefault", () => {
|
||||
const event = new SubmitEvent("submit");
|
||||
const spy = jest.spyOn(event, "preventDefault");
|
||||
|
||||
onSubmitPreventDefault(event);
|
||||
expect(spy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { mocked, type Mocked } from "jest-mock";
|
||||
import { mocked, type Mocked } from "jest-mock-vitest-adapter";
|
||||
import { type MatrixClient, type Room } from "matrix-js-sdk/src/matrix";
|
||||
import { sleep } from "matrix-js-sdk/src/utils";
|
||||
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import { EnhancedMap, mapDiff } from "../../../src/utils/maps";
|
||||
|
||||
describe("maps", () => {
|
||||
describe("mapDiff", () => {
|
||||
it("should indicate no differences when the pointers are the same", () => {
|
||||
const a = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
]);
|
||||
const result = mapDiff(a, a);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("should indicate no differences when there are none", () => {
|
||||
const a = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
]);
|
||||
const b = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
]);
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("should indicate added properties", () => {
|
||||
const a = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
]);
|
||||
const b = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
[4, 4],
|
||||
]);
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(0);
|
||||
expect(result.added).toEqual([4]);
|
||||
});
|
||||
|
||||
it("should indicate removed properties", () => {
|
||||
const a = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
]);
|
||||
const b = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
]);
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.changed).toHaveLength(0);
|
||||
expect(result.removed).toEqual([3]);
|
||||
});
|
||||
|
||||
it("should indicate changed properties", () => {
|
||||
const a = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
]);
|
||||
const b = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 4],
|
||||
]); // note change
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(1);
|
||||
expect(result.changed).toEqual([3]);
|
||||
});
|
||||
|
||||
it("should indicate changed, added, and removed properties", () => {
|
||||
const a = new Map([
|
||||
[1, 1],
|
||||
[2, 2],
|
||||
[3, 3],
|
||||
]);
|
||||
const b = new Map([
|
||||
[1, 1],
|
||||
[2, 8],
|
||||
[4, 4],
|
||||
]); // note change
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(1);
|
||||
expect(result.removed).toHaveLength(1);
|
||||
expect(result.changed).toHaveLength(1);
|
||||
expect(result.added).toEqual([4]);
|
||||
expect(result.removed).toEqual([3]);
|
||||
expect(result.changed).toEqual([2]);
|
||||
});
|
||||
|
||||
it("should indicate changes for difference in pointers", () => {
|
||||
const a = new Map([[1, {}]]); // {} always creates a new object
|
||||
const b = new Map([[1, {}]]);
|
||||
const result = mapDiff(a, b);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.added).toBeDefined();
|
||||
expect(result.removed).toBeDefined();
|
||||
expect(result.changed).toBeDefined();
|
||||
expect(result.added).toHaveLength(0);
|
||||
expect(result.removed).toHaveLength(0);
|
||||
expect(result.changed).toHaveLength(1);
|
||||
expect(result.changed).toEqual([1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("EnhancedMap", () => {
|
||||
// Most of these tests will make sure it implements the Map<K, V> class
|
||||
|
||||
it("should be empty by default", () => {
|
||||
const result = new EnhancedMap();
|
||||
expect(result.size).toBe(0);
|
||||
});
|
||||
|
||||
it("should use the provided entries", () => {
|
||||
const obj = { a: 1, b: 2 };
|
||||
const result = new EnhancedMap(Object.entries(obj));
|
||||
expect(result.size).toBe(2);
|
||||
expect(result.get("a")).toBe(1);
|
||||
expect(result.get("b")).toBe(2);
|
||||
});
|
||||
|
||||
it("should create keys if they do not exist", () => {
|
||||
const key = "a";
|
||||
const val = {}; // we'll check pointers
|
||||
|
||||
const result = new EnhancedMap<string, any>();
|
||||
expect(result.size).toBe(0);
|
||||
|
||||
let get = result.getOrCreate(key, val);
|
||||
expect(get).toBeDefined();
|
||||
expect(get).toBe(val);
|
||||
expect(result.size).toBe(1);
|
||||
|
||||
get = result.getOrCreate(key, 44); // specifically change `val`
|
||||
expect(get).toBeDefined();
|
||||
expect(get).toBe(val);
|
||||
expect(result.size).toBe(1);
|
||||
|
||||
get = result.get(key); // use the base class function
|
||||
expect(get).toBeDefined();
|
||||
expect(get).toBe(val);
|
||||
expect(result.size).toBe(1);
|
||||
});
|
||||
|
||||
it("should proxy remove to delete and return it", () => {
|
||||
const val = {};
|
||||
const result = new EnhancedMap<string, any>();
|
||||
result.set("a", val);
|
||||
|
||||
expect(result.size).toBe(1);
|
||||
|
||||
const removed = result.remove("a");
|
||||
expect(result.size).toBe(0);
|
||||
expect(removed).toBeDefined();
|
||||
expect(removed).toBe(val);
|
||||
});
|
||||
|
||||
it("should support removing unknown keys", () => {
|
||||
const val = {};
|
||||
const result = new EnhancedMap<string, any>();
|
||||
result.set("a", val);
|
||||
|
||||
expect(result.size).toBe(1);
|
||||
|
||||
const removed = result.remove("not-a");
|
||||
expect(result.size).toBe(1);
|
||||
expect(removed).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
ReceiptType,
|
||||
type AccountDataEvents,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { type Mocked, mocked } from "jest-mock";
|
||||
import { type Mocked, mocked } from "jest-mock-vitest-adapter";
|
||||
|
||||
import {
|
||||
localNotificationsAreSilenced,
|
||||
|
||||
@@ -382,10 +382,10 @@ describe("Permalinks", function () {
|
||||
});
|
||||
|
||||
it("should generate a room permalink for room IDs with some candidate servers", function () {
|
||||
mockClient.getRoom.mockImplementation((roomId: Room["roomId"]) => {
|
||||
return mockRoom(roomId, [
|
||||
makeMemberWithPL(roomId, "@alice:first", 100),
|
||||
makeMemberWithPL(roomId, "@bob:second", 0),
|
||||
mockClient.getRoom.mockImplementation((roomId?: string) => {
|
||||
return mockRoom(roomId!, [
|
||||
makeMemberWithPL(roomId!, "@alice:first", 100),
|
||||
makeMemberWithPL(roomId!, "@bob:second", 0),
|
||||
]);
|
||||
});
|
||||
const result = makeRoomPermalink(mockClient, "!somewhere:example.org");
|
||||
@@ -399,10 +399,10 @@ describe("Permalinks", function () {
|
||||
});
|
||||
|
||||
it("should generate a room permalink for room aliases without candidate servers", function () {
|
||||
mockClient.getRoom.mockImplementation((roomId: Room["roomId"]) => {
|
||||
return mockRoom(roomId, [
|
||||
makeMemberWithPL(roomId, "@alice:first", 100),
|
||||
makeMemberWithPL(roomId, "@bob:second", 0),
|
||||
mockClient.getRoom.mockImplementation((roomId?: string) => {
|
||||
return mockRoom(roomId!, [
|
||||
makeMemberWithPL(roomId!, "@alice:first", 100),
|
||||
makeMemberWithPL(roomId!, "@bob:second", 0),
|
||||
]);
|
||||
});
|
||||
const result = makeRoomPermalink(mockClient, "#somewhere:example.org");
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { MatrixError, type MatrixClient } from "matrix-js-sdk/src/matrix";
|
||||
import { waitFor } from "jest-matrix-react";
|
||||
|
||||
import type { MockedObject } from "jest-mock";
|
||||
import type { MockedObject } from "jest-mock-vitest-adapter";
|
||||
import { UserMenuViewModel } from "../../../src/viewmodels/menus/UserMenuViewModel";
|
||||
import { getMockClientWithEventEmitter, mockClientMethodsServer, mockClientMethodsUser } from "../../test-utils";
|
||||
import { MatrixDispatcher } from "../../../src/dispatcher/dispatcher";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { expect } from "@jest/globals";
|
||||
|
||||
import type { MockedObject } from "jest-mock";
|
||||
import type { MockedObject } from "jest-mock-vitest-adapter";
|
||||
import type { MatrixClient, IPreviewUrlResponse } from "matrix-js-sdk/src/matrix";
|
||||
import {
|
||||
BUNDLED_LINK_PREVIEWS,
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
EventStatus,
|
||||
} from "matrix-js-sdk/src/matrix";
|
||||
import { RoomStatusBarState } from "@element-hq/web-shared-components";
|
||||
import { type MockedObject } from "jest-mock";
|
||||
import { type MockedObject } from "jest-mock-vitest-adapter";
|
||||
|
||||
import { mkEvent, mkRoom, stubClient } from "../../test-utils";
|
||||
import { RoomStatusBarViewModel } from "../../../src/viewmodels/room/RoomStatusBar";
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
import { type MatrixClient, type Room, RoomEvent } from "matrix-js-sdk/src/matrix";
|
||||
import { type MockedObject } from "jest-mock";
|
||||
import { type MockedObject } from "jest-mock-vitest-adapter";
|
||||
import { createRef } from "react";
|
||||
|
||||
import { mkRoom, stubClient } from "../../test-utils";
|
||||
|
||||
Reference in New Issue
Block a user