Add MatrixClientPeg::safeGet and use it in tests (#10985)

This commit is contained in:
Michael Telatynski 2023-06-05 18:12:23 +01:00 committed by GitHub
parent c47b587225
commit 6b46d6e4f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
88 changed files with 290 additions and 226 deletions

View file

@ -38,7 +38,7 @@ import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } fro
import SecurityCustomisations from "./customisations/Security"; import SecurityCustomisations from "./customisations/Security";
import { SlidingSyncManager } from "./SlidingSyncManager"; import { SlidingSyncManager } from "./SlidingSyncManager";
import CryptoStoreTooNewDialog from "./components/views/dialogs/CryptoStoreTooNewDialog"; import CryptoStoreTooNewDialog from "./components/views/dialogs/CryptoStoreTooNewDialog";
import { _t } from "./languageHandler"; import { _t, UserFriendlyError } from "./languageHandler";
import { SettingLevel } from "./settings/SettingLevel"; import { SettingLevel } from "./settings/SettingLevel";
import MatrixClientBackedController from "./settings/controllers/MatrixClientBackedController"; import MatrixClientBackedController from "./settings/controllers/MatrixClientBackedController";
import ErrorDialog from "./components/views/dialogs/ErrorDialog"; import ErrorDialog from "./components/views/dialogs/ErrorDialog";
@ -49,7 +49,7 @@ export interface IMatrixClientCreds {
identityServerUrl?: string; identityServerUrl?: string;
userId: string; userId: string;
deviceId?: string; deviceId?: string;
accessToken: string; accessToken?: string;
guest?: boolean; guest?: boolean;
pickleKey?: string; pickleKey?: string;
freshLogin?: boolean; freshLogin?: boolean;
@ -71,9 +71,10 @@ export interface IMatrixClientPeg {
* *
* @returns {string} The homeserver name, if present. * @returns {string} The homeserver name, if present.
*/ */
getHomeserverName(): string; getHomeserverName(): string | null;
get(): MatrixClient; get(): MatrixClient;
safeGet(): MatrixClient;
unset(): void; unset(): void;
assign(): Promise<any>; assign(): Promise<any>;
start(): Promise<any>; start(): Promise<any>;
@ -134,7 +135,7 @@ class MatrixClientPegClass implements IMatrixClientPeg {
initialSyncLimit: 20, initialSyncLimit: 20,
}; };
private matrixClient: MatrixClient = null; private matrixClient: MatrixClient | null = null;
private justRegisteredUserId: string | null = null; private justRegisteredUserId: string | null = null;
// the credentials used to init the current client object. // the credentials used to init the current client object.
@ -145,6 +146,13 @@ class MatrixClientPegClass implements IMatrixClientPeg {
return this.matrixClient; return this.matrixClient;
} }
public safeGet(): MatrixClient {
if (!this.matrixClient) {
throw new UserFriendlyError("User is not logged in");
}
return this.matrixClient;
}
public unset(): void { public unset(): void {
this.matrixClient = null; this.matrixClient = null;
@ -215,6 +223,10 @@ class MatrixClientPegClass implements IMatrixClientPeg {
}; };
public async assign(): Promise<any> { public async assign(): Promise<any> {
if (!this.matrixClient) {
throw new Error("createClient must be called first");
}
for (const dbType of ["indexeddb", "memory"]) { for (const dbType of ["indexeddb", "memory"]) {
try { try {
const promise = this.matrixClient.store.startup(); const promise = this.matrixClient.store.startup();
@ -275,6 +287,10 @@ class MatrixClientPegClass implements IMatrixClientPeg {
* Attempt to initialize the crypto layer on a newly-created MatrixClient * Attempt to initialize the crypto layer on a newly-created MatrixClient
*/ */
private async initClientCrypto(): Promise<void> { private async initClientCrypto(): Promise<void> {
if (!this.matrixClient) {
throw new Error("createClient must be called first");
}
const useRustCrypto = SettingsStore.getValue("feature_rust_crypto"); const useRustCrypto = SettingsStore.getValue("feature_rust_crypto");
// we want to make sure that the same crypto implementation is used throughout the lifetime of a device, // we want to make sure that the same crypto implementation is used throughout the lifetime of a device,
@ -317,11 +333,15 @@ class MatrixClientPegClass implements IMatrixClientPeg {
const opts = await this.assign(); const opts = await this.assign();
logger.log(`MatrixClientPeg: really starting MatrixClient`); logger.log(`MatrixClientPeg: really starting MatrixClient`);
await this.get().startClient(opts); await this.matrixClient!.startClient(opts);
logger.log(`MatrixClientPeg: MatrixClient started`); logger.log(`MatrixClientPeg: MatrixClient started`);
} }
public getCredentials(): IMatrixClientCreds { public getCredentials(): IMatrixClientCreds {
if (!this.matrixClient) {
throw new Error("createClient must be called first");
}
let copiedCredentials: IMatrixClientCreds | null = this.currentClientCreds; let copiedCredentials: IMatrixClientCreds | null = this.currentClientCreds;
if (this.currentClientCreds?.userId !== this.matrixClient?.credentials?.userId) { if (this.currentClientCreds?.userId !== this.matrixClient?.credentials?.userId) {
// cached credentials belong to a different user - don't use them // cached credentials belong to a different user - don't use them
@ -335,12 +355,14 @@ class MatrixClientPegClass implements IMatrixClientPeg {
identityServerUrl: this.matrixClient.idBaseUrl, identityServerUrl: this.matrixClient.idBaseUrl,
userId: this.matrixClient.getSafeUserId(), userId: this.matrixClient.getSafeUserId(),
deviceId: this.matrixClient.getDeviceId() ?? undefined, deviceId: this.matrixClient.getDeviceId() ?? undefined,
accessToken: this.matrixClient.getAccessToken(), accessToken: this.matrixClient.getAccessToken() ?? undefined,
guest: this.matrixClient.isGuest(), guest: this.matrixClient.isGuest(),
}; };
} }
public getHomeserverName(): string { public getHomeserverName(): string | null {
if (!this.matrixClient) return null;
const matches = /^@[^:]+:(.+)$/.exec(this.matrixClient.getSafeUserId()); const matches = /^@[^:]+:(.+)$/.exec(this.matrixClient.getSafeUserId());
if (matches === null || matches.length < 1) { if (matches === null || matches.length < 1) {
throw new Error("Failed to derive homeserver name from user ID!"); throw new Error("Failed to derive homeserver name from user ID!");

View file

@ -91,7 +91,7 @@ const msgTypeHandlers: Record<string, (event: MatrixEvent) => string | null> = {
return null; return null;
} }
return TextForEvent.textForEvent(event); return TextForEvent.textForEvent(event, MatrixClientPeg.get());
}, },
}; };
@ -111,7 +111,7 @@ class NotifierClass {
if (msgType && msgTypeHandlers.hasOwnProperty(msgType)) { if (msgType && msgTypeHandlers.hasOwnProperty(msgType)) {
return msgTypeHandlers[msgType](ev); return msgTypeHandlers[msgType](ev);
} }
return TextForEvent.textForEvent(ev); return TextForEvent.textForEvent(ev, MatrixClientPeg.get());
} }
// XXX: exported for tests // XXX: exported for tests

View file

@ -22,6 +22,7 @@ import { GuestAccess, HistoryVisibility, JoinRule } from "matrix-js-sdk/src/@typ
import { EventType, MsgType } from "matrix-js-sdk/src/@types/event"; import { EventType, MsgType } from "matrix-js-sdk/src/@types/event";
import { M_POLL_START, M_POLL_END } from "matrix-js-sdk/src/@types/polls"; import { M_POLL_START, M_POLL_END } from "matrix-js-sdk/src/@types/polls";
import { PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent"; import { PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { _t } from "./languageHandler"; import { _t } from "./languageHandler";
import * as Roles from "./Roles"; import * as Roles from "./Roles";
@ -31,7 +32,6 @@ import { ALL_RULE_TYPES, ROOM_RULE_TYPES, SERVER_RULE_TYPES, USER_RULE_TYPES } f
import { WIDGET_LAYOUT_EVENT_TYPE } from "./stores/widgets/WidgetLayoutStore"; import { WIDGET_LAYOUT_EVENT_TYPE } from "./stores/widgets/WidgetLayoutStore";
import { RightPanelPhases } from "./stores/right-panel/RightPanelStorePhases"; import { RightPanelPhases } from "./stores/right-panel/RightPanelStorePhases";
import defaultDispatcher from "./dispatcher/dispatcher"; import defaultDispatcher from "./dispatcher/dispatcher";
import { MatrixClientPeg } from "./MatrixClientPeg";
import { RoomSettingsTab } from "./components/views/dialogs/RoomSettingsDialog"; import { RoomSettingsTab } from "./components/views/dialogs/RoomSettingsDialog";
import AccessibleButton, { ButtonEvent } from "./components/views/elements/AccessibleButton"; import AccessibleButton, { ButtonEvent } from "./components/views/elements/AccessibleButton";
import RightPanelStore from "./stores/right-panel/RightPanelStore"; import RightPanelStore from "./stores/right-panel/RightPanelStore";
@ -40,16 +40,15 @@ import { ElementCall } from "./models/Call";
import { textForVoiceBroadcastStoppedEvent, VoiceBroadcastInfoEventType } from "./voice-broadcast"; import { textForVoiceBroadcastStoppedEvent, VoiceBroadcastInfoEventType } from "./voice-broadcast";
import { getSenderName } from "./utils/event/getSenderName"; import { getSenderName } from "./utils/event/getSenderName";
function getRoomMemberDisplayname(event: MatrixEvent, userId = event.getSender()): string { function getRoomMemberDisplayname(client: MatrixClient, event: MatrixEvent, userId = event.getSender()): string {
const client = MatrixClientPeg.get();
const roomId = event.getRoomId(); const roomId = event.getRoomId();
const member = client.getRoom(roomId)?.getMember(userId!); const member = client.getRoom(roomId)?.getMember(userId!);
return member?.name || member?.rawDisplayName || userId || _t("Someone"); return member?.name || member?.rawDisplayName || userId || _t("Someone");
} }
function textForCallEvent(event: MatrixEvent): () => string { function textForCallEvent(event: MatrixEvent, client: MatrixClient): () => string {
const roomName = MatrixClientPeg.get().getRoom(event.getRoomId()!)?.name; const roomName = client.getRoom(event.getRoomId()!)?.name;
const isSupported = MatrixClientPeg.get().supportsVoip(); const isSupported = client.supportsVoip();
return isSupported return isSupported
? () => _t("Video call started in %(roomName)s.", { roomName }) ? () => _t("Video call started in %(roomName)s.", { roomName })
@ -60,11 +59,11 @@ function textForCallEvent(event: MatrixEvent): () => string {
// any text to display at all. For this reason they return deferred values // any text to display at all. For this reason they return deferred values
// to avoid the expense of looking up translations when they're not needed. // to avoid the expense of looking up translations when they're not needed.
function textForCallInviteEvent(event: MatrixEvent): (() => string) | null { function textForCallInviteEvent(event: MatrixEvent, client: MatrixClient): (() => string) | null {
const senderName = getSenderName(event); const senderName = getSenderName(event);
// FIXME: Find a better way to determine this from the event? // FIXME: Find a better way to determine this from the event?
const isVoice = !event.getContent().offer?.sdp?.includes("m=video"); const isVoice = !event.getContent().offer?.sdp?.includes("m=video");
const isSupported = MatrixClientPeg.get().supportsVoip(); const isSupported = client.supportsVoip();
// This ladder could be reduced down to a couple string variables, however other languages // This ladder could be reduced down to a couple string variables, however other languages
// can have a hard time translating those strings. In an effort to make translations easier // can have a hard time translating those strings. In an effort to make translations easier
@ -103,10 +102,15 @@ function getModification(prev?: string, value?: string): Modification {
return Modification.None; return Modification.None;
} }
function textForMemberEvent(ev: MatrixEvent, allowJSX: boolean, showHiddenEvents?: boolean): (() => string) | null { function textForMemberEvent(
ev: MatrixEvent,
client: MatrixClient,
allowJSX: boolean,
showHiddenEvents?: boolean,
): (() => string) | null {
// XXX: SYJS-16 "sender is sometimes null for join messages" // XXX: SYJS-16 "sender is sometimes null for join messages"
const senderName = ev.sender?.name || getRoomMemberDisplayname(ev); const senderName = ev.sender?.name || getRoomMemberDisplayname(client, ev);
const targetName = ev.target?.name || getRoomMemberDisplayname(ev, ev.getStateKey()); const targetName = ev.target?.name || getRoomMemberDisplayname(client, ev, ev.getStateKey());
const prevContent = ev.getPrevContent(); const prevContent = ev.getPrevContent();
const content = ev.getContent(); const content = ev.getContent();
const reason = content.reason; const reason = content.reason;
@ -269,7 +273,7 @@ const onViewJoinRuleSettingsClick = (): void => {
}); });
}; };
function textForJoinRulesEvent(ev: MatrixEvent, allowJSX: boolean): () => Renderable { function textForJoinRulesEvent(ev: MatrixEvent, client: MatrixClient, allowJSX: boolean): () => Renderable {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
switch (ev.getContent().join_rule) { switch (ev.getContent().join_rule) {
case JoinRule.Public: case JoinRule.Public:
@ -361,7 +365,7 @@ function textForServerACLEvent(ev: MatrixEvent): (() => string) | null {
return getText; return getText;
} }
function textForMessageEvent(ev: MatrixEvent): (() => string) | null { function textForMessageEvent(ev: MatrixEvent, client: MatrixClient): (() => string) | null {
if (isLocationEvent(ev)) { if (isLocationEvent(ev)) {
return textForLocationEvent(ev); return textForLocationEvent(ev);
} }
@ -370,7 +374,7 @@ function textForMessageEvent(ev: MatrixEvent): (() => string) | null {
const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender(); const senderDisplayName = ev.sender && ev.sender.name ? ev.sender.name : ev.getSender();
let message = ev.getContent().body; let message = ev.getContent().body;
if (ev.isRedacted()) { if (ev.isRedacted()) {
message = textForRedactedPollAndMessageEvent(ev); message = textForRedactedPollAndMessageEvent(ev, client);
} }
if (ev.getContent().msgtype === MsgType.Emote) { if (ev.getContent().msgtype === MsgType.Emote) {
@ -496,7 +500,7 @@ function textForHistoryVisibilityEvent(event: MatrixEvent): (() => string) | nul
} }
// Currently will only display a change if a user's power level is changed // Currently will only display a change if a user's power level is changed
function textForPowerEvent(event: MatrixEvent): (() => string) | null { function textForPowerEvent(event: MatrixEvent, client: MatrixClient): (() => string) | null {
const senderName = getSenderName(event); const senderName = getSenderName(event);
if (!event.getPrevContent()?.users || !event.getContent()?.users) { if (!event.getPrevContent()?.users || !event.getContent()?.users) {
return null; return null;
@ -533,7 +537,7 @@ function textForPowerEvent(event: MatrixEvent): (() => string) | null {
return; return;
} }
if (to !== from) { if (to !== from) {
const name = getRoomMemberDisplayname(event, userId); const name = getRoomMemberDisplayname(client, event, userId);
diffs.push({ userId, name, from, to }); diffs.push({ userId, name, from, to });
} }
}); });
@ -561,7 +565,7 @@ const onPinnedMessagesClick = (): void => {
RightPanelStore.instance.setCard({ phase: RightPanelPhases.PinnedMessages }, false); RightPanelStore.instance.setCard({ phase: RightPanelPhases.PinnedMessages }, false);
}; };
function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): (() => Renderable) | null { function textForPinnedEvent(event: MatrixEvent, client: MatrixClient, allowJSX: boolean): (() => Renderable) | null {
if (!SettingsStore.getValue("feature_pinning")) return null; if (!SettingsStore.getValue("feature_pinning")) return null;
const senderName = getSenderName(event); const senderName = getSenderName(event);
const roomId = event.getRoomId()!; const roomId = event.getRoomId()!;
@ -835,12 +839,12 @@ export function textForLocationEvent(event: MatrixEvent): () => string {
}); });
} }
function textForRedactedPollAndMessageEvent(ev: MatrixEvent): string { function textForRedactedPollAndMessageEvent(ev: MatrixEvent, client: MatrixClient): string {
let message = _t("Message deleted"); let message = _t("Message deleted");
const unsigned = ev.getUnsigned(); const unsigned = ev.getUnsigned();
const redactedBecauseUserId = unsigned?.redacted_because?.sender; const redactedBecauseUserId = unsigned?.redacted_because?.sender;
if (redactedBecauseUserId && redactedBecauseUserId !== ev.getSender()) { if (redactedBecauseUserId && redactedBecauseUserId !== ev.getSender()) {
const room = MatrixClientPeg.get().getRoom(ev.getRoomId()); const room = client.getRoom(ev.getRoomId());
const sender = room?.getMember(redactedBecauseUserId); const sender = room?.getMember(redactedBecauseUserId);
message = _t("Message deleted by %(name)s", { message = _t("Message deleted by %(name)s", {
name: sender?.name || redactedBecauseUserId, name: sender?.name || redactedBecauseUserId,
@ -850,12 +854,12 @@ function textForRedactedPollAndMessageEvent(ev: MatrixEvent): string {
return message; return message;
} }
function textForPollStartEvent(event: MatrixEvent): (() => string) | null { function textForPollStartEvent(event: MatrixEvent, client: MatrixClient): (() => string) | null {
return () => { return () => {
let message = ""; let message = "";
if (event.isRedacted()) { if (event.isRedacted()) {
message = textForRedactedPollAndMessageEvent(event); message = textForRedactedPollAndMessageEvent(event, client);
const senderDisplayName = event.sender?.name ?? event.getSender(); const senderDisplayName = event.sender?.name ?? event.getSender();
message = senderDisplayName + ": " + message; message = senderDisplayName + ": " + message;
} else { } else {
@ -879,7 +883,12 @@ function textForPollEndEvent(event: MatrixEvent): (() => string) | null {
type Renderable = string | React.ReactNode | null; type Renderable = string | React.ReactNode | null;
interface IHandlers { interface IHandlers {
[type: string]: (ev: MatrixEvent, allowJSX: boolean, showHiddenEvents?: boolean) => (() => Renderable) | null; [type: string]: (
ev: MatrixEvent,
client: MatrixClient,
allowJSX: boolean,
showHiddenEvents?: boolean,
) => (() => Renderable) | null;
} }
const handlers: IHandlers = { const handlers: IHandlers = {
@ -925,25 +934,39 @@ for (const evType of ElementCall.CALL_EVENT_TYPE.names) {
/** /**
* Determines whether the given event has text to display. * Determines whether the given event has text to display.
*
* @param client The Matrix Client instance for the logged-in user
* @param ev The event * @param ev The event
* @param showHiddenEvents An optional cached setting value for showHiddenEventsInTimeline * @param showHiddenEvents An optional cached setting value for showHiddenEventsInTimeline
* to avoid hitting the settings store * to avoid hitting the settings store
*/ */
export function hasText(ev: MatrixEvent, showHiddenEvents?: boolean): boolean { export function hasText(ev: MatrixEvent, client: MatrixClient, showHiddenEvents?: boolean): boolean {
const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()]; const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
return Boolean(handler?.(ev, false, showHiddenEvents)); return Boolean(handler?.(ev, client, false, showHiddenEvents));
} }
/** /**
* Gets the textual content of the given event. * Gets the textual content of the given event.
*
* @param ev The event * @param ev The event
* @param client The Matrix Client instance for the logged-in user
* @param allowJSX Whether to output rich JSX content * @param allowJSX Whether to output rich JSX content
* @param showHiddenEvents An optional cached setting value for showHiddenEventsInTimeline * @param showHiddenEvents An optional cached setting value for showHiddenEventsInTimeline
* to avoid hitting the settings store * to avoid hitting the settings store
*/ */
export function textForEvent(ev: MatrixEvent): string; export function textForEvent(ev: MatrixEvent, client: MatrixClient): string;
export function textForEvent(ev: MatrixEvent, allowJSX: true, showHiddenEvents?: boolean): string | React.ReactNode; export function textForEvent(
export function textForEvent(ev: MatrixEvent, allowJSX = false, showHiddenEvents?: boolean): string | React.ReactNode { ev: MatrixEvent,
client: MatrixClient,
allowJSX: true,
showHiddenEvents?: boolean,
): string | React.ReactNode;
export function textForEvent(
ev: MatrixEvent,
client: MatrixClient,
allowJSX = false,
showHiddenEvents?: boolean,
): string | React.ReactNode {
const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()]; const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
return handler?.(ev, allowJSX, showHiddenEvents)?.() || ""; return handler?.(ev, client, allowJSX, showHiddenEvents)?.() || "";
} }

View file

@ -1301,7 +1301,7 @@ class MainGrouper extends BaseGrouper {
public add({ event: ev, shouldShow }: EventAndShouldShow): void { public add({ event: ev, shouldShow }: EventAndShouldShow): void {
if (ev.getType() === EventType.RoomMember) { if (ev.getType() === EventType.RoomMember) {
// We can ignore any events that don't actually have a message to display // We can ignore any events that don't actually have a message to display
if (!hasText(ev, this.panel.showHiddenEvents)) return; if (!hasText(ev, MatrixClientPeg.get(), this.panel.showHiddenEvents)) return;
} }
this.readMarker = this.readMarker || this.panel.readMarkerForEvent(ev.getId()!, ev === this.lastShownEvent); this.readMarker = this.readMarker || this.panel.readMarkerForEvent(ev.getId()!, ev === this.lastShownEvent);
if (!this.panel.showHiddenEvents && !shouldShow) { if (!this.panel.showHiddenEvents && !shouldShow) {

View file

@ -20,7 +20,7 @@ import { M_TEXT } from "matrix-js-sdk/src/@types/extensible_events";
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { Icon as PollIcon } from "../../../../res/img/element-icons/room/composer/poll.svg"; import { Icon as PollIcon } from "../../../../res/img/element-icons/room/composer/poll.svg";
import MatrixClientContext from "../../../contexts/MatrixClientContext"; import MatrixClientContext, { useMatrixClientContext } from "../../../contexts/MatrixClientContext";
import { _t } from "../../../languageHandler"; import { _t } from "../../../languageHandler";
import { textForEvent } from "../../../TextForEvent"; import { textForEvent } from "../../../TextForEvent";
import { Caption } from "../typography/Caption"; import { Caption } from "../typography/Caption";
@ -95,10 +95,11 @@ const usePollStartEvent = (event: MatrixEvent): { pollStartEvent?: MatrixEvent;
}; };
export const MPollEndBody = React.forwardRef<any, IBodyProps>(({ mxEvent, ...props }, ref) => { export const MPollEndBody = React.forwardRef<any, IBodyProps>(({ mxEvent, ...props }, ref) => {
const cli = useMatrixClientContext();
const { pollStartEvent, isLoadingPollStartEvent } = usePollStartEvent(mxEvent); const { pollStartEvent, isLoadingPollStartEvent } = usePollStartEvent(mxEvent);
if (!pollStartEvent) { if (!pollStartEvent) {
const pollEndFallbackMessage = M_TEXT.findIn(mxEvent.getContent()) || textForEvent(mxEvent); const pollEndFallbackMessage = M_TEXT.findIn(mxEvent.getContent()) || textForEvent(mxEvent, cli);
return ( return (
<> <>
<PollIcon className="mx_MPollEndBody_icon" /> <PollIcon className="mx_MPollEndBody_icon" />

View file

@ -19,6 +19,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
import RoomContext from "../../../contexts/RoomContext"; import RoomContext from "../../../contexts/RoomContext";
import * as TextForEvent from "../../../TextForEvent"; import * as TextForEvent from "../../../TextForEvent";
import { MatrixClientPeg } from "../../../MatrixClientPeg";
interface IProps { interface IProps {
mxEvent: MatrixEvent; mxEvent: MatrixEvent;
@ -28,7 +29,12 @@ export default class TextualEvent extends React.Component<IProps> {
public static contextType = RoomContext; public static contextType = RoomContext;
public render(): React.ReactNode { public render(): React.ReactNode {
const text = TextForEvent.textForEvent(this.props.mxEvent, true, this.context?.showHiddenEvents); const text = TextForEvent.textForEvent(
this.props.mxEvent,
MatrixClientPeg.get(),
true,
this.context?.showHiddenEvents,
);
if (!text) return null; if (!text) return null;
return <div className="mx_TextualEvent">{text}</div>; return <div className="mx_TextualEvent">{text}</div>;
} }

View file

@ -255,7 +255,7 @@ export function pickFactory(
return noEventFactoryFactory(); // improper event type to render return noEventFactoryFactory(); // improper event type to render
} }
if (STATE_EVENT_TILE_TYPES.get(evType) === TextualEventFactory && !hasText(mxEvent, showHiddenEvents)) { if (STATE_EVENT_TILE_TYPES.get(evType) === TextualEventFactory && !hasText(mxEvent, cli, showHiddenEvents)) {
return noEventFactoryFactory(); return noEventFactoryFactory();
} }
@ -435,7 +435,7 @@ export function haveRendererForEvent(mxEvent: MatrixEvent, showHiddenEvents: boo
const handler = pickFactory(mxEvent, cli, showHiddenEvents); const handler = pickFactory(mxEvent, cli, showHiddenEvents);
if (!handler) return false; if (!handler) return false;
if (handler === TextualEventFactory) { if (handler === TextualEventFactory) {
return hasText(mxEvent, showHiddenEvents); return hasText(mxEvent, cli, showHiddenEvents);
} else if (handler === STATE_EVENT_TILE_TYPES.get(EventType.RoomCreate)) { } else if (handler === STATE_EVENT_TILE_TYPES.get(EventType.RoomCreate)) {
const dynamicPredecessorsEnabled = SettingsStore.getValue("feature_dynamic_room_predecessors"); const dynamicPredecessorsEnabled = SettingsStore.getValue("feature_dynamic_room_predecessors");
const predecessor = cli.getRoom(mxEvent.getRoomId())?.findPredecessor(dynamicPredecessorsEnabled); const predecessor = cli.getRoom(mxEvent.getRoomId())?.findPredecessor(dynamicPredecessorsEnabled);

View file

@ -104,6 +104,7 @@
"We couldn't log you in": "We couldn't log you in", "We couldn't log you in": "We couldn't log you in",
"We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.", "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.": "We asked the browser to remember which homeserver you use to let you sign in, but unfortunately your browser has forgotten it. Go to the sign in page and try again.",
"Try again": "Try again", "Try again": "Try again",
"User is not logged in": "User is not logged in",
"Database unexpectedly closed": "Database unexpectedly closed", "Database unexpectedly closed": "Database unexpectedly closed",
"This may be caused by having the app open in multiple tabs or due to clearing browser data.": "This may be caused by having the app open in multiple tabs or due to clearing browser data.", "This may be caused by having the app open in multiple tabs or due to clearing browser data.": "This may be caused by having the app open in multiple tabs or due to clearing browser data.",
"Reload": "Reload", "Reload": "Reload",

View file

@ -402,7 +402,7 @@ export default class HTMLExporter extends Exporter {
// TODO: Handle callEvent errors // TODO: Handle callEvent errors
logger.error(e); logger.error(e);
eventTile = await this.getEventTileMarkup( eventTile = await this.getEventTileMarkup(
this.createModifiedEvent(textForEvent(mxEv), mxEv, false), this.createModifiedEvent(textForEvent(mxEv, this.room.client), mxEv, false),
joined, joined,
); );
} }

View file

@ -104,7 +104,7 @@ export default class PlainTextExporter extends Exporter {
} else mediaText = ` (${this.mediaOmitText})`; } else mediaText = ` (${this.mediaOmitText})`;
} }
if (this.isReply(mxEv)) return senderDisplayName + ": " + this.textForReplyEvent(mxEv.getContent()) + mediaText; if (this.isReply(mxEv)) return senderDisplayName + ": " + this.textForReplyEvent(mxEv.getContent()) + mediaText;
else return textForEvent(mxEv) + mediaText; else return textForEvent(mxEv, this.room.client) + mediaText;
}; };
protected async createOutput(events: MatrixEvent[]): Promise<string> { protected async createOutput(events: MatrixEvent[]): Promise<string> {

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import React, { ReactNode } from "react"; import React, { ReactNode } from "react";
import { MatrixEvent } from "matrix-js-sdk/src/matrix"; import { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "../../MatrixClientPeg"; import { MatrixClientPeg } from "../../MatrixClientPeg";
import AccessibleButton from "../../components/views/elements/AccessibleButton"; import AccessibleButton from "../../components/views/elements/AccessibleButton";
@ -23,7 +23,7 @@ import { highlightEvent } from "../../utils/EventUtils";
import { _t } from "../../languageHandler"; import { _t } from "../../languageHandler";
import { getSenderName } from "../../utils/event/getSenderName"; import { getSenderName } from "../../utils/event/getSenderName";
export const textForVoiceBroadcastStoppedEvent = (event: MatrixEvent): (() => ReactNode) => { export const textForVoiceBroadcastStoppedEvent = (event: MatrixEvent, client: MatrixClient): (() => ReactNode) => {
return (): ReactNode => { return (): ReactNode => {
const ownUserId = MatrixClientPeg.get()?.getUserId(); const ownUserId = MatrixClientPeg.get()?.getUserId();
const startEventId = event.getRelation()?.event_id; const startEventId = event.getRelation()?.event_id;

View file

@ -95,7 +95,7 @@ const VIRTUAL_ROOM_BOB = "$virtual_bob_room:example.org";
const BOB_PHONE_NUMBER = "01818118181"; const BOB_PHONE_NUMBER = "01818118181";
function mkStubDM(roomId: string, userId: string) { function mkStubDM(roomId: string, userId: string) {
const room = mkStubRoom(roomId, "room", MatrixClientPeg.get()); const room = mkStubRoom(roomId, "room", MatrixClientPeg.safeGet());
room.getJoinedMembers = jest.fn().mockReturnValue([ room.getJoinedMembers = jest.fn().mockReturnValue([
{ {
userId: "@me:example.org", userId: "@me:example.org",
@ -169,16 +169,16 @@ describe("LegacyCallHandler", () => {
beforeEach(async () => { beforeEach(async () => {
stubClient(); stubClient();
fakeCall = null; fakeCall = null;
MatrixClientPeg.get().createCall = (roomId: string): MatrixCall | null => { MatrixClientPeg.safeGet().createCall = (roomId: string): MatrixCall | null => {
if (fakeCall && fakeCall.roomId !== roomId) { if (fakeCall && fakeCall.roomId !== roomId) {
throw new Error("Only one call is supported!"); throw new Error("Only one call is supported!");
} }
fakeCall = new FakeCall(roomId) as unknown as MatrixCall; fakeCall = new FakeCall(roomId) as unknown as MatrixCall;
return fakeCall as unknown as MatrixCall; return fakeCall as unknown as MatrixCall;
}; };
MatrixClientPeg.get().deviceId = deviceId; MatrixClientPeg.safeGet().deviceId = deviceId;
MatrixClientPeg.get().getThirdpartyProtocols = () => { MatrixClientPeg.safeGet().getThirdpartyProtocols = () => {
return Promise.resolve({ return Promise.resolve({
"m.id.phone": {} as IProtocol, "m.id.phone": {} as IProtocol,
"im.vector.protocol.sip_native": {} as IProtocol, "im.vector.protocol.sip_native": {} as IProtocol,
@ -196,7 +196,7 @@ describe("LegacyCallHandler", () => {
const nativeRoomCharie = mkStubDM(NATIVE_ROOM_CHARLIE, NATIVE_CHARLIE); const nativeRoomCharie = mkStubDM(NATIVE_ROOM_CHARLIE, NATIVE_CHARLIE);
const virtualBobRoom = mkStubDM(VIRTUAL_ROOM_BOB, VIRTUAL_BOB); const virtualBobRoom = mkStubDM(VIRTUAL_ROOM_BOB, VIRTUAL_BOB);
MatrixClientPeg.get().getRoom = (roomId: string): Room | null => { MatrixClientPeg.safeGet().getRoom = (roomId: string): Room | null => {
switch (roomId) { switch (roomId) {
case NATIVE_ROOM_ALICE: case NATIVE_ROOM_ALICE:
return nativeRoomAlice; return nativeRoomAlice;
@ -244,7 +244,7 @@ describe("LegacyCallHandler", () => {
pstnLookup = null; pstnLookup = null;
nativeLookup = null; nativeLookup = null;
MatrixClientPeg.get().getThirdpartyUser = (proto: string, params: any) => { MatrixClientPeg.safeGet().getThirdpartyUser = (proto: string, params: any) => {
if ([PROTOCOL_PSTN, PROTOCOL_PSTN_PREFIXED].includes(proto)) { if ([PROTOCOL_PSTN, PROTOCOL_PSTN_PREFIXED].includes(proto)) {
pstnLookup = params["m.id.phone"]; pstnLookup = params["m.id.phone"];
return Promise.resolve([ return Promise.resolve([
@ -402,10 +402,10 @@ describe("LegacyCallHandler", () => {
mkVoiceBroadcastInfoStateEvent( mkVoiceBroadcastInfoStateEvent(
"!room:example.com", "!room:example.com",
VoiceBroadcastInfoState.Started, VoiceBroadcastInfoState.Started,
MatrixClientPeg.get().getSafeUserId(), MatrixClientPeg.safeGet().getSafeUserId(),
"d42", "d42",
), ),
MatrixClientPeg.get(), MatrixClientPeg.safeGet(),
SdkContextClass.instance.voiceBroadcastRecordingsStore, SdkContextClass.instance.voiceBroadcastRecordingsStore,
); );
SdkContextClass.instance.voiceBroadcastPlaybacksStore.setCurrent(voiceBroadcastPlayback); SdkContextClass.instance.voiceBroadcastPlaybacksStore.setCurrent(voiceBroadcastPlayback);
@ -427,10 +427,10 @@ describe("LegacyCallHandler", () => {
mkVoiceBroadcastInfoStateEvent( mkVoiceBroadcastInfoStateEvent(
"!room:example.com", "!room:example.com",
VoiceBroadcastInfoState.Started, VoiceBroadcastInfoState.Started,
MatrixClientPeg.get().getSafeUserId(), MatrixClientPeg.safeGet().getSafeUserId(),
"d42", "d42",
), ),
MatrixClientPeg.get(), MatrixClientPeg.safeGet(),
), ),
); );
}); });
@ -451,7 +451,7 @@ describe("LegacyCallHandler without third party protocols", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
fakeCall = null; fakeCall = null;
MatrixClientPeg.get().createCall = (roomId) => { MatrixClientPeg.safeGet().createCall = (roomId) => {
if (fakeCall && fakeCall.roomId !== roomId) { if (fakeCall && fakeCall.roomId !== roomId) {
throw new Error("Only one call is supported!"); throw new Error("Only one call is supported!");
} }
@ -459,7 +459,7 @@ describe("LegacyCallHandler without third party protocols", () => {
return fakeCall; return fakeCall;
}; };
MatrixClientPeg.get().getThirdpartyProtocols = () => { MatrixClientPeg.safeGet().getThirdpartyProtocols = () => {
throw new Error("Endpoint unsupported."); throw new Error("Endpoint unsupported.");
}; };
@ -468,7 +468,7 @@ describe("LegacyCallHandler without third party protocols", () => {
const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE); const nativeRoomAlice = mkStubDM(NATIVE_ROOM_ALICE, NATIVE_ALICE);
MatrixClientPeg.get().getRoom = (roomId: string): Room | null => { MatrixClientPeg.safeGet().getRoom = (roomId: string): Room | null => {
switch (roomId) { switch (roomId) {
case NATIVE_ROOM_ALICE: case NATIVE_ROOM_ALICE:
return nativeRoomAlice; return nativeRoomAlice;
@ -495,7 +495,7 @@ describe("LegacyCallHandler without third party protocols", () => {
} as DMRoomMap; } as DMRoomMap;
DMRoomMap.setShared(dmRoomMap); DMRoomMap.setShared(dmRoomMap);
MatrixClientPeg.get().getThirdpartyUser = (_proto, _params) => { MatrixClientPeg.safeGet().getThirdpartyUser = (_proto, _params) => {
throw new Error("Endpoint unsupported."); throw new Error("Endpoint unsupported.");
}; };
@ -547,12 +547,12 @@ describe("LegacyCallHandler without third party protocols", () => {
jest.clearAllMocks(); jest.clearAllMocks();
jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => setting === UIFeature.Voip); jest.spyOn(SettingsStore, "getValue").mockImplementation((setting) => setting === UIFeature.Voip);
jest.spyOn(MatrixClientPeg.get(), "supportsVoip").mockReturnValue(true); jest.spyOn(MatrixClientPeg.safeGet(), "supportsVoip").mockReturnValue(true);
MatrixClientPeg.get().isFallbackICEServerAllowed = jest.fn(); MatrixClientPeg.safeGet().isFallbackICEServerAllowed = jest.fn();
MatrixClientPeg.get().prepareToEncrypt = jest.fn(); MatrixClientPeg.safeGet().prepareToEncrypt = jest.fn();
MatrixClientPeg.get().pushRules = { MatrixClientPeg.safeGet().pushRules = {
global: { global: {
[PushRuleKind.Override]: [ [PushRuleKind.Override]: [
{ {
@ -573,7 +573,7 @@ describe("LegacyCallHandler without third party protocols", () => {
jest.spyOn(document, "getElementById").mockReturnValue(mockAudioElement); jest.spyOn(document, "getElementById").mockReturnValue(mockAudioElement);
// silence local notifications by default // silence local notifications by default
jest.spyOn(MatrixClientPeg.get(), "getAccountData").mockImplementation((eventType) => { jest.spyOn(MatrixClientPeg.safeGet(), "getAccountData").mockImplementation((eventType) => {
if (eventType.includes(LOCAL_NOTIFICATION_SETTINGS_PREFIX.name)) { if (eventType.includes(LOCAL_NOTIFICATION_SETTINGS_PREFIX.name)) {
return new MatrixEvent({ return new MatrixEvent({
type: eventType, type: eventType,
@ -600,10 +600,10 @@ describe("LegacyCallHandler without third party protocols", () => {
it("listens for incoming call events when voip is enabled", () => { it("listens for incoming call events when voip is enabled", () => {
const call = new MatrixCall({ const call = new MatrixCall({
client: MatrixClientPeg.get(), client: MatrixClientPeg.safeGet(),
roomId, roomId,
}); });
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
cli.emit(CallEventHandlerEvent.Incoming, call); cli.emit(CallEventHandlerEvent.Incoming, call);
@ -613,12 +613,12 @@ describe("LegacyCallHandler without third party protocols", () => {
it("rings when incoming call state is ringing and notifications set to ring", () => { it("rings when incoming call state is ringing and notifications set to ring", () => {
// remove local notification silencing mock for this test // remove local notification silencing mock for this test
jest.spyOn(MatrixClientPeg.get(), "getAccountData").mockReturnValue(undefined); jest.spyOn(MatrixClientPeg.safeGet(), "getAccountData").mockReturnValue(undefined);
const call = new MatrixCall({ const call = new MatrixCall({
client: MatrixClientPeg.get(), client: MatrixClientPeg.safeGet(),
roomId, roomId,
}); });
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
cli.emit(CallEventHandlerEvent.Incoming, call); cli.emit(CallEventHandlerEvent.Incoming, call);
@ -632,10 +632,10 @@ describe("LegacyCallHandler without third party protocols", () => {
it("does not ring when incoming call state is ringing but local notifications are silenced", () => { it("does not ring when incoming call state is ringing but local notifications are silenced", () => {
const call = new MatrixCall({ const call = new MatrixCall({
client: MatrixClientPeg.get(), client: MatrixClientPeg.safeGet(),
roomId, roomId,
}); });
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
cli.emit(CallEventHandlerEvent.Incoming, call); cli.emit(CallEventHandlerEvent.Incoming, call);
@ -650,10 +650,10 @@ describe("LegacyCallHandler without third party protocols", () => {
it("should force calls to silent when local notifications are silenced", async () => { it("should force calls to silent when local notifications are silenced", async () => {
const call = new MatrixCall({ const call = new MatrixCall({
client: MatrixClientPeg.get(), client: MatrixClientPeg.safeGet(),
roomId, roomId,
}); });
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
cli.emit(CallEventHandlerEvent.Incoming, call); cli.emit(CallEventHandlerEvent.Incoming, call);
@ -663,10 +663,10 @@ describe("LegacyCallHandler without third party protocols", () => {
it("does not unsilence calls when local notifications are silenced", async () => { it("does not unsilence calls when local notifications are silenced", async () => {
const call = new MatrixCall({ const call = new MatrixCall({
client: MatrixClientPeg.get(), client: MatrixClientPeg.safeGet(),
roomId, roomId,
}); });
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
const callHandlerEmitSpy = jest.spyOn(callHandler, "emit"); const callHandlerEmitSpy = jest.spyOn(callHandler, "emit");
cli.emit(CallEventHandlerEvent.Incoming, call); cli.emit(CallEventHandlerEvent.Incoming, call);

View file

@ -44,7 +44,7 @@ describe("MatrixClientPeg", () => {
stubClient(); stubClient();
(peg as any).matrixClient = peg.get(); (peg as any).matrixClient = peg.get();
peg.setJustRegisteredUserId("@userId:matrix.org"); peg.setJustRegisteredUserId("@userId:matrix.org");
expect(peg.get().credentials.userId).toBe("@userId:matrix.org"); expect(peg.safeGet().credentials.userId).toBe("@userId:matrix.org");
expect(peg.currentUserIsJustRegistered()).toBe(true); expect(peg.currentUserIsJustRegistered()).toBe(true);
expect(peg.userRegisteredWithinLastHours(0)).toBe(false); expect(peg.userRegisteredWithinLastHours(0)).toBe(false);
expect(peg.userRegisteredWithinLastHours(1)).toBe(true); expect(peg.userRegisteredWithinLastHours(1)).toBe(true);
@ -89,11 +89,11 @@ describe("MatrixClientPeg", () => {
}); });
it("should initialise client crypto", async () => { it("should initialise client crypto", async () => {
const mockInitCrypto = jest.spyOn(testPeg.get(), "initCrypto").mockResolvedValue(undefined); const mockInitCrypto = jest.spyOn(testPeg.safeGet(), "initCrypto").mockResolvedValue(undefined);
const mockSetTrustCrossSignedDevices = jest const mockSetTrustCrossSignedDevices = jest
.spyOn(testPeg.get(), "setCryptoTrustCrossSignedDevices") .spyOn(testPeg.safeGet(), "setCryptoTrustCrossSignedDevices")
.mockImplementation(() => {}); .mockImplementation(() => {});
const mockStartClient = jest.spyOn(testPeg.get(), "startClient").mockResolvedValue(undefined); const mockStartClient = jest.spyOn(testPeg.safeGet(), "startClient").mockResolvedValue(undefined);
await testPeg.start(); await testPeg.start();
expect(mockInitCrypto).toHaveBeenCalledTimes(1); expect(mockInitCrypto).toHaveBeenCalledTimes(1);
@ -103,11 +103,11 @@ describe("MatrixClientPeg", () => {
it("should carry on regardless if there is an error initialising crypto", async () => { it("should carry on regardless if there is an error initialising crypto", async () => {
const e2eError = new Error("nope nope nope"); const e2eError = new Error("nope nope nope");
const mockInitCrypto = jest.spyOn(testPeg.get(), "initCrypto").mockRejectedValue(e2eError); const mockInitCrypto = jest.spyOn(testPeg.safeGet(), "initCrypto").mockRejectedValue(e2eError);
const mockSetTrustCrossSignedDevices = jest const mockSetTrustCrossSignedDevices = jest
.spyOn(testPeg.get(), "setCryptoTrustCrossSignedDevices") .spyOn(testPeg.safeGet(), "setCryptoTrustCrossSignedDevices")
.mockImplementation(() => {}); .mockImplementation(() => {});
const mockStartClient = jest.spyOn(testPeg.get(), "startClient").mockResolvedValue(undefined); const mockStartClient = jest.spyOn(testPeg.safeGet(), "startClient").mockResolvedValue(undefined);
const mockWarning = jest.spyOn(logger, "warn").mockReturnValue(undefined); const mockWarning = jest.spyOn(logger, "warn").mockReturnValue(undefined);
await testPeg.start(); await testPeg.start();
@ -130,8 +130,8 @@ describe("MatrixClientPeg", () => {
const mockSetValue = jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined); const mockSetValue = jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined);
const mockInitCrypto = jest.spyOn(testPeg.get(), "initCrypto").mockResolvedValue(undefined); const mockInitCrypto = jest.spyOn(testPeg.safeGet(), "initCrypto").mockResolvedValue(undefined);
const mockInitRustCrypto = jest.spyOn(testPeg.get(), "initRustCrypto").mockResolvedValue(undefined); const mockInitRustCrypto = jest.spyOn(testPeg.safeGet(), "initRustCrypto").mockResolvedValue(undefined);
await testPeg.start(); await testPeg.start();
expect(mockInitCrypto).not.toHaveBeenCalled(); expect(mockInitCrypto).not.toHaveBeenCalled();
@ -142,9 +142,9 @@ describe("MatrixClientPeg", () => {
}); });
it("should reload when store database closes for a guest user", async () => { it("should reload when store database closes for a guest user", async () => {
testPeg.get().isGuest = () => true; testPeg.safeGet().isGuest = () => true;
const emitter = new EventEmitter(); const emitter = new EventEmitter();
testPeg.get().store.on = emitter.on.bind(emitter); testPeg.safeGet().store.on = emitter.on.bind(emitter);
const platform: any = { reload: jest.fn() }; const platform: any = { reload: jest.fn() };
PlatformPeg.set(platform); PlatformPeg.set(platform);
await testPeg.assign(); await testPeg.assign();
@ -153,9 +153,9 @@ describe("MatrixClientPeg", () => {
}); });
it("should show error modal when store database closes", async () => { it("should show error modal when store database closes", async () => {
testPeg.get().isGuest = () => false; testPeg.safeGet().isGuest = () => false;
const emitter = new EventEmitter(); const emitter = new EventEmitter();
testPeg.get().store.on = emitter.on.bind(emitter); testPeg.safeGet().store.on = emitter.on.bind(emitter);
const spy = jest.spyOn(Modal, "createDialog"); const spy = jest.spyOn(Modal, "createDialog");
await testPeg.assign(); await testPeg.assign();
emitter.emit("closed" as any); emitter.emit("closed" as any);

View file

@ -54,7 +54,7 @@ describe("MediaDeviceHandler", () => {
expect(SettingsStoreMock.setValue).toHaveBeenCalledWith(key, null, SettingLevel.DEVICE, value); expect(SettingsStoreMock.setValue).toHaveBeenCalledWith(key, null, SettingLevel.DEVICE, value);
}); });
expect(MatrixClientPeg.get().getMediaHandler().setAudioSettings).toHaveBeenCalledWith({ expect(MatrixClientPeg.safeGet().getMediaHandler().setAudioSettings).toHaveBeenCalledWith({
autoGainControl: false, autoGainControl: false,
echoCancellation: true, echoCancellation: true,
noiseSuppression: false, noiseSuppression: false,

View file

@ -47,6 +47,8 @@ function mockPinnedEvent(pinnedMessageIds?: string[], prevPinnedMessageIds?: str
} }
describe("TextForEvent", () => { describe("TextForEvent", () => {
const mockClient = createTestClient();
describe("getSenderName()", () => { describe("getSenderName()", () => {
it("Prefers sender.name", () => { it("Prefers sender.name", () => {
expect(getSenderName({ sender: { name: "Alice" } } as MatrixEvent)).toBe("Alice"); expect(getSenderName({ sender: { name: "Alice" } } as MatrixEvent)).toBe("Alice");
@ -67,8 +69,8 @@ describe("TextForEvent", () => {
it("mentions message when a single message was pinned, with no previously pinned messages", () => { it("mentions message when a single message was pinned, with no previously pinned messages", () => {
const event = mockPinnedEvent(["message-1"]); const event = mockPinnedEvent(["message-1"]);
const plainText = textForEvent(event); const plainText = textForEvent(event, mockClient);
const component = render(textForEvent(event, true) as ReactElement); const component = render(textForEvent(event, mockClient, true) as ReactElement);
const expectedText = "@foo:example.com pinned a message to this room. See all pinned messages."; const expectedText = "@foo:example.com pinned a message to this room. See all pinned messages.";
expect(plainText).toBe(expectedText); expect(plainText).toBe(expectedText);
@ -77,8 +79,8 @@ describe("TextForEvent", () => {
it("mentions message when a single message was pinned, with multiple previously pinned messages", () => { it("mentions message when a single message was pinned, with multiple previously pinned messages", () => {
const event = mockPinnedEvent(["message-1", "message-2", "message-3"], ["message-1", "message-2"]); const event = mockPinnedEvent(["message-1", "message-2", "message-3"], ["message-1", "message-2"]);
const plainText = textForEvent(event); const plainText = textForEvent(event, mockClient);
const component = render(textForEvent(event, true) as ReactElement); const component = render(textForEvent(event, mockClient, true) as ReactElement);
const expectedText = "@foo:example.com pinned a message to this room. See all pinned messages."; const expectedText = "@foo:example.com pinned a message to this room. See all pinned messages.";
expect(plainText).toBe(expectedText); expect(plainText).toBe(expectedText);
@ -87,8 +89,8 @@ describe("TextForEvent", () => {
it("mentions message when a single message was unpinned, with a single message previously pinned", () => { it("mentions message when a single message was unpinned, with a single message previously pinned", () => {
const event = mockPinnedEvent([], ["message-1"]); const event = mockPinnedEvent([], ["message-1"]);
const plainText = textForEvent(event); const plainText = textForEvent(event, mockClient);
const component = render(textForEvent(event, true) as ReactElement); const component = render(textForEvent(event, mockClient, true) as ReactElement);
const expectedText = "@foo:example.com unpinned a message from this room. See all pinned messages."; const expectedText = "@foo:example.com unpinned a message from this room. See all pinned messages.";
expect(plainText).toBe(expectedText); expect(plainText).toBe(expectedText);
@ -97,8 +99,8 @@ describe("TextForEvent", () => {
it("mentions message when a single message was unpinned, with multiple previously pinned messages", () => { it("mentions message when a single message was unpinned, with multiple previously pinned messages", () => {
const event = mockPinnedEvent(["message-2"], ["message-1", "message-2"]); const event = mockPinnedEvent(["message-2"], ["message-1", "message-2"]);
const plainText = textForEvent(event); const plainText = textForEvent(event, mockClient);
const component = render(textForEvent(event, true) as ReactElement); const component = render(textForEvent(event, mockClient, true) as ReactElement);
const expectedText = "@foo:example.com unpinned a message from this room. See all pinned messages."; const expectedText = "@foo:example.com unpinned a message from this room. See all pinned messages.";
expect(plainText).toBe(expectedText); expect(plainText).toBe(expectedText);
@ -107,8 +109,8 @@ describe("TextForEvent", () => {
it("shows generic text when multiple messages were pinned", () => { it("shows generic text when multiple messages were pinned", () => {
const event = mockPinnedEvent(["message-1", "message-2", "message-3"], ["message-1"]); const event = mockPinnedEvent(["message-1", "message-2", "message-3"], ["message-1"]);
const plainText = textForEvent(event); const plainText = textForEvent(event, mockClient);
const component = render(textForEvent(event, true) as ReactElement); const component = render(textForEvent(event, mockClient, true) as ReactElement);
const expectedText = "@foo:example.com changed the pinned messages for the room."; const expectedText = "@foo:example.com changed the pinned messages for the room.";
expect(plainText).toBe(expectedText); expect(plainText).toBe(expectedText);
@ -117,8 +119,8 @@ describe("TextForEvent", () => {
it("shows generic text when multiple messages were unpinned", () => { it("shows generic text when multiple messages were unpinned", () => {
const event = mockPinnedEvent(["message-3"], ["message-1", "message-2", "message-3"]); const event = mockPinnedEvent(["message-3"], ["message-1", "message-2", "message-3"]);
const plainText = textForEvent(event); const plainText = textForEvent(event, mockClient);
const component = render(textForEvent(event, true) as ReactElement); const component = render(textForEvent(event, mockClient, true) as ReactElement);
const expectedText = "@foo:example.com changed the pinned messages for the room."; const expectedText = "@foo:example.com changed the pinned messages for the room.";
expect(plainText).toBe(expectedText); expect(plainText).toBe(expectedText);
@ -127,8 +129,8 @@ describe("TextForEvent", () => {
it("shows generic text when one message was pinned, and another unpinned", () => { it("shows generic text when one message was pinned, and another unpinned", () => {
const event = mockPinnedEvent(["message-2"], ["message-1"]); const event = mockPinnedEvent(["message-2"], ["message-1"]);
const plainText = textForEvent(event); const plainText = textForEvent(event, mockClient);
const component = render(textForEvent(event, true) as ReactElement); const component = render(textForEvent(event, mockClient, true) as ReactElement);
const expectedText = "@foo:example.com changed the pinned messages for the room."; const expectedText = "@foo:example.com changed the pinned messages for the room.";
expect(plainText).toBe(expectedText); expect(plainText).toBe(expectedText);
@ -184,6 +186,7 @@ describe("TextForEvent", () => {
beforeAll(() => { beforeAll(() => {
mockClient = createTestClient() as Mocked<MatrixClient>; mockClient = createTestClient() as Mocked<MatrixClient>;
MatrixClientPeg.get = () => mockClient; MatrixClientPeg.get = () => mockClient;
MatrixClientPeg.safeGet = () => mockClient;
mockClient.getRoom.mockClear().mockReturnValue(mockRoom); mockClient.getRoom.mockClear().mockReturnValue(mockRoom);
mockRoom.getMember mockRoom.getMember
.mockClear() .mockClear()
@ -206,7 +209,7 @@ describe("TextForEvent", () => {
[userA.userId]: 100, [userA.userId]: 100,
}, },
}); });
expect(textForEvent(event)).toBeFalsy(); expect(textForEvent(event, mockClient)).toBeFalsy();
}); });
it("returns false when users power levels have been changed by default settings", () => { it("returns false when users power levels have been changed by default settings", () => {
@ -220,7 +223,7 @@ describe("TextForEvent", () => {
[userA.userId]: 50, [userA.userId]: 50,
}, },
}); });
expect(textForEvent(event)).toBeFalsy(); expect(textForEvent(event, mockClient)).toBeFalsy();
}); });
it("returns correct message for a single user with changed power level", () => { it("returns correct message for a single user with changed power level", () => {
@ -233,7 +236,7 @@ describe("TextForEvent", () => {
}, },
}); });
const expectedText = "Alice changed the power level of Bob (@b) from Moderator to Admin."; const expectedText = "Alice changed the power level of Bob (@b) from Moderator to Admin.";
expect(textForEvent(event)).toEqual(expectedText); expect(textForEvent(event, mockClient)).toEqual(expectedText);
}); });
it("returns correct message for a single user with power level changed to the default", () => { it("returns correct message for a single user with power level changed to the default", () => {
@ -248,7 +251,7 @@ describe("TextForEvent", () => {
}, },
}); });
const expectedText = "Alice changed the power level of Bob (@b) from Moderator to Default."; const expectedText = "Alice changed the power level of Bob (@b) from Moderator to Default.";
expect(textForEvent(event)).toEqual(expectedText); expect(textForEvent(event, mockClient)).toEqual(expectedText);
}); });
it("returns correct message for a single user with power level changed to a custom level", () => { it("returns correct message for a single user with power level changed to a custom level", () => {
@ -261,7 +264,7 @@ describe("TextForEvent", () => {
}, },
}); });
const expectedText = "Alice changed the power level of Bob (@b) from Moderator to Custom (-1)."; const expectedText = "Alice changed the power level of Bob (@b) from Moderator to Custom (-1).";
expect(textForEvent(event)).toEqual(expectedText); expect(textForEvent(event, mockClient)).toEqual(expectedText);
}); });
it("returns correct message for a multiple power level changes", () => { it("returns correct message for a multiple power level changes", () => {
@ -278,7 +281,7 @@ describe("TextForEvent", () => {
const expectedText = const expectedText =
"Alice changed the power level of Bob (@b) from Moderator to Admin," + "Alice changed the power level of Bob (@b) from Moderator to Admin," +
" Bob (@c) from Custom (101) to Moderator."; " Bob (@c) from Custom (101) to Moderator.";
expect(textForEvent(event)).toEqual(expectedText); expect(textForEvent(event, mockClient)).toEqual(expectedText);
}); });
}); });
@ -382,7 +385,7 @@ describe("TextForEvent", () => {
it.each(testCases)("returns correct message when %s", (_d, { result, ...eventProps }) => { it.each(testCases)("returns correct message when %s", (_d, { result, ...eventProps }) => {
const event = mockEvent(eventProps); const event = mockEvent(eventProps);
expect(textForEvent(event)).toEqual(result); expect(textForEvent(event, mockClient)).toEqual(result);
}); });
}); });
@ -409,11 +412,11 @@ describe("TextForEvent", () => {
it("returns correct message for redacted poll start", () => { it("returns correct message for redacted poll start", () => {
pollEvent.makeRedacted(pollEvent); pollEvent.makeRedacted(pollEvent);
expect(textForEvent(pollEvent)).toEqual("@a: Message deleted"); expect(textForEvent(pollEvent, mockClient)).toEqual("@a: Message deleted");
}); });
it("returns correct message for normal poll start", () => { it("returns correct message for normal poll start", () => {
expect(textForEvent(pollEvent)).toEqual("@a has started a poll - "); expect(textForEvent(pollEvent, mockClient)).toEqual("@a has started a poll - ");
}); });
}); });
@ -435,11 +438,11 @@ describe("TextForEvent", () => {
it("returns correct message for redacted message", () => { it("returns correct message for redacted message", () => {
messageEvent.makeRedacted(messageEvent); messageEvent.makeRedacted(messageEvent);
expect(textForEvent(messageEvent)).toEqual("@a: Message deleted"); expect(textForEvent(messageEvent, mockClient)).toEqual("@a: Message deleted");
}); });
it("returns correct message for normal message", () => { it("returns correct message for normal message", () => {
expect(textForEvent(messageEvent)).toEqual("@a: test message"); expect(textForEvent(messageEvent, mockClient)).toEqual("@a: test message");
}); });
}); });
@ -449,7 +452,7 @@ describe("TextForEvent", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
mockClient = MatrixClientPeg.get(); mockClient = MatrixClientPeg.safeGet();
mocked(mockClient.getRoom).mockReturnValue({ mocked(mockClient.getRoom).mockReturnValue({
name: "Test room", name: "Test room",
@ -468,13 +471,13 @@ describe("TextForEvent", () => {
}); });
it("returns correct message for call event when supported", () => { it("returns correct message for call event when supported", () => {
expect(textForEvent(callEvent)).toEqual("Video call started in Test room."); expect(textForEvent(callEvent, mockClient)).toEqual("Video call started in Test room.");
}); });
it("returns correct message for call event when not supported", () => { it("returns correct message for call event when not supported", () => {
mocked(mockClient).supportsVoip.mockReturnValue(false); mocked(mockClient).supportsVoip.mockReturnValue(false);
expect(textForEvent(callEvent)).toEqual( expect(textForEvent(callEvent, mockClient)).toEqual(
"Video call started in Test room. (not supported by this browser)", "Video call started in Test room. (not supported by this browser)",
); );
}); });
@ -504,6 +507,7 @@ describe("TextForEvent", () => {
}, },
state_key: "@a:foo", state_key: "@a:foo",
}), }),
mockClient,
), ),
).toMatchInlineSnapshot(`"Andy changed their display name and profile picture"`); ).toMatchInlineSnapshot(`"Andy changed their display name and profile picture"`);
}); });

View file

@ -33,7 +33,7 @@ describe("Unread", () => {
// A different user. // A different user.
const aliceId = "@alice:server.org"; const aliceId = "@alice:server.org";
stubClient(); stubClient();
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
describe("eventTriggersUnreadCount()", () => { describe("eventTriggersUnreadCount()", () => {
// setup events // setup events

View file

@ -44,7 +44,7 @@ const TOO_SHORT_EMOJI_SHORTCODE = [{ emojiShortcode: ":o", expectedEmoji: "⭕
describe("EmojiProvider", function () { describe("EmojiProvider", function () {
const testRoom = mkStubRoom(undefined, undefined, undefined); const testRoom = mkStubRoom(undefined, undefined, undefined);
stubClient(); stubClient();
MatrixClientPeg.get(); MatrixClientPeg.safeGet();
it.each(EMOJI_SHORTCODES)("Returns consistent results after final colon %s", async function (emojiShortcode) { it.each(EMOJI_SHORTCODES)("Returns consistent results after final colon %s", async function (emojiShortcode) {
const ep = new EmojiProvider(testRoom); const ep = new EmojiProvider(testRoom);

View file

@ -30,7 +30,7 @@ let client: MatrixClient;
describe("LegacyCallEventGrouper", () => { describe("LegacyCallEventGrouper", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
client.getUserId = () => { client.getUserId = () => {
return MY_USER_ID; return MY_USER_ID;
}; };

View file

@ -90,7 +90,7 @@ describe("PipContainer", () => {
user = userEvent.setup(); user = userEvent.setup();
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
DMRoomMap.makeShared(client); DMRoomMap.makeShared(client);
room = new Room("!1:example.org", client, "@alice:example.org", { room = new Room("!1:example.org", client, "@alice:example.org", {

View file

@ -47,7 +47,7 @@ describe("RightPanel", () => {
let RightPanel: React.ComponentType<React.ComponentProps<typeof RightPanelBase>>; let RightPanel: React.ComponentType<React.ComponentProps<typeof RightPanelBase>>;
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = mocked(MatrixClientPeg.get()); cli = mocked(MatrixClientPeg.safeGet());
DMRoomMap.makeShared(cli); DMRoomMap.makeShared(cli);
context = new SdkContextClass(); context = new SdkContextClass();
context.client = cli; context.client = cli;

View file

@ -45,7 +45,7 @@ describe("<RoomSearchView/>", () => {
beforeEach(async () => { beforeEach(async () => {
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
client.supportsThreads = jest.fn().mockReturnValue(true); client.supportsThreads = jest.fn().mockReturnValue(true);
room = new Room("!room:server", client, client.getSafeUserId()); room = new Room("!room:server", client, client.getSafeUserId());
mocked(client.getRoom).mockReturnValue(room); mocked(client.getRoom).mockReturnValue(room);

View file

@ -37,7 +37,7 @@ describe("RoomStatusBar", () => {
jest.clearAllMocks(); jest.clearAllMocks();
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
client.getSyncStateData = jest.fn().mockReturnValue({}); client.getSyncStateData = jest.fn().mockReturnValue({});
room = new Room(ROOM_ID, client, client.getUserId()!, { room = new Room(ROOM_ID, client, client.getUserId()!, {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -76,7 +76,7 @@ describe("RoomView", () => {
beforeEach(() => { beforeEach(() => {
mockPlatformPeg({ reload: () => {} }); mockPlatformPeg({ reload: () => {} });
stubClient(); stubClient();
cli = mocked(MatrixClientPeg.get()); cli = mocked(MatrixClientPeg.safeGet());
room = new Room(`!${roomCount++}:example.org`, cli, "@alice:example.org"); room = new Room(`!${roomCount++}:example.org`, cli, "@alice:example.org");
jest.spyOn(room, "findPredecessor"); jest.spyOn(room, "findPredecessor");

View file

@ -43,7 +43,7 @@ describe("SpaceHierarchy", () => {
let room: Room; let room: Room;
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
room = new Room("room-id", client, "@alice:example.com"); room = new Room("room-id", client, "@alice:example.com");
hierarchy = new RoomHierarchy(room); hierarchy = new RoomHierarchy(room);
@ -82,7 +82,7 @@ describe("SpaceHierarchy", () => {
describe("toLocalRoom", () => { describe("toLocalRoom", () => {
stubClient(); stubClient();
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
const roomV1 = mkStubRoom("room-id-1", "Room V1", client); const roomV1 = mkStubRoom("room-id-1", "Room V1", client);
const roomV2 = mkStubRoom("room-id-2", "Room V2", client); const roomV2 = mkStubRoom("room-id-2", "Room V2", client);
const roomV3 = mkStubRoom("room-id-3", "Room V3", client); const roomV3 = mkStubRoom("room-id-3", "Room V3", client);
@ -171,7 +171,7 @@ describe("SpaceHierarchy", () => {
}); });
stubClient(); stubClient();
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
const dmRoomMap = { const dmRoomMap = {
getUserIdForRoomId: jest.fn(), getUserIdForRoomId: jest.fn(),

View file

@ -120,7 +120,7 @@ describe("ThreadPanel", () => {
stubClient(); stubClient();
mockPlatformPeg(); mockPlatformPeg();
mockClient = mocked(MatrixClientPeg.get()); mockClient = mocked(MatrixClientPeg.safeGet());
Thread.setServerSideSupport(FeatureSupport.Stable); Thread.setServerSideSupport(FeatureSupport.Stable);
Thread.setServerSideListSupport(FeatureSupport.Stable); Thread.setServerSideListSupport(FeatureSupport.Stable);
Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable); Thread.setServerSideFwdPaginationSupport(FeatureSupport.Stable);

View file

@ -115,7 +115,7 @@ describe("ThreadView", () => {
stubClient(); stubClient();
mockPlatformPeg(); mockPlatformPeg();
mockClient = mocked(MatrixClientPeg.get()); mockClient = mocked(MatrixClientPeg.safeGet());
jest.spyOn(mockClient, "supportsThreads").mockReturnValue(true); jest.spyOn(mockClient, "supportsThreads").mockReturnValue(true);
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", { room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {

View file

@ -106,7 +106,7 @@ const mockEvents = (room: Room, count = 2): MatrixEvent[] => {
}; };
const setupTestData = (): [MatrixClient, Room, MatrixEvent[]] => { const setupTestData = (): [MatrixClient, Room, MatrixEvent[]] => {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
const room = mkRoom(client, "roomId"); const room = mkRoom(client, "roomId");
const events = mockEvents(room); const events = mockEvents(room);
return [client, room, events]; return [client, room, events];
@ -377,7 +377,7 @@ describe("TimelinePanel", () => {
}); });
it("should scroll event into view when props.eventId changes", () => { it("should scroll event into view when props.eventId changes", () => {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
const room = mkRoom(client, "roomId"); const room = mkRoom(client, "roomId");
const events = mockEvents(room); const events = mockEvents(room);
@ -798,7 +798,7 @@ describe("TimelinePanel", () => {
let reply2: MatrixEvent; let reply2: MatrixEvent;
beforeEach(() => { beforeEach(() => {
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
Thread.hasServerSideSupport = FeatureSupport.Stable; Thread.hasServerSideSupport = FeatureSupport.Stable;
room = new Room("roomId", client, "userId"); room = new Room("roomId", client, "userId");
@ -952,7 +952,7 @@ describe("TimelinePanel", () => {
}); });
it("renders when the last message is an undecryptable thread root", async () => { it("renders when the last message is an undecryptable thread root", async () => {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
client.isRoomEncrypted = () => true; client.isRoomEncrypted = () => true;
client.supportsThreads = () => true; client.supportsThreads = () => true;
client.decryptEventIfNeeded = () => Promise.resolve(); client.decryptEventIfNeeded = () => Promise.resolve();

View file

@ -47,7 +47,7 @@ describe("MemberAvatar", () => {
jest.clearAllMocks(); jest.clearAllMocks();
stubClient(); stubClient();
mockClient = mocked(MatrixClientPeg.get()); mockClient = mocked(MatrixClientPeg.safeGet());
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", { room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -41,7 +41,7 @@ describe("<RoomCallBanner />", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
room = new Room("!1:example.org", client, "@alice:example.org", { room = new Room("!1:example.org", client, "@alice:example.org", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -159,7 +159,7 @@ describe("MessageContextMenu", () => {
room_id: roomId, room_id: roomId,
}); });
pinnableEvent.event.event_id = "!3"; pinnableEvent.event.event_id = "!3";
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
const room = makeDefaultRoom(); const room = makeDefaultRoom();
// mock permission to allow adding pinned messages to room // mock permission to allow adding pinned messages to room
@ -204,7 +204,7 @@ describe("MessageContextMenu", () => {
room_id: roomId, room_id: roomId,
}); });
pinnableEvent.event.event_id = "!3"; pinnableEvent.event.event_id = "!3";
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
const room = makeDefaultRoom(); const room = makeDefaultRoom();
// make the event already pinned in the room // make the event already pinned in the room
@ -543,7 +543,7 @@ function createMenuWithContent(
} }
function makeDefaultRoom(): Room { function makeDefaultRoom(): Room {
return new Room(roomId, MatrixClientPeg.get(), "@user:example.com", { return new Room(roomId, MatrixClientPeg.safeGet(), "@user:example.com", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,
}); });
} }
@ -555,7 +555,7 @@ function createMenu(
beacons: Map<BeaconIdentifier, Beacon> = new Map(), beacons: Map<BeaconIdentifier, Beacon> = new Map(),
room: Room = makeDefaultRoom(), room: Room = makeDefaultRoom(),
): RenderResult { ): RenderResult {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
// @ts-ignore illegally set private prop // @ts-ignore illegally set private prop
room.currentState.beacons = beacons; room.currentState.beacons = beacons;

View file

@ -46,7 +46,7 @@ describe("RoomContextMenu", () => {
jest.clearAllMocks(); jest.clearAllMocks();
stubClient(); stubClient();
mockClient = mocked(MatrixClientPeg.get()); mockClient = mocked(MatrixClientPeg.safeGet());
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", { room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -71,7 +71,7 @@ describe("RoomGeneralContextMenu", () => {
jest.clearAllMocks(); jest.clearAllMocks();
stubClient(); stubClient();
mockClient = mocked(MatrixClientPeg.get()); mockClient = mocked(MatrixClientPeg.safeGet());
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", { room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -45,7 +45,7 @@ describe("ThreadListContextMenu", () => {
jest.clearAllMocks(); jest.clearAllMocks();
stubClient(); stubClient();
mockClient = mocked(MatrixClientPeg.get()); mockClient = mocked(MatrixClientPeg.safeGet());
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", { room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -39,7 +39,7 @@ describe("DevtoolsDialog", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
room = new Room("!id", cli, "@alice:matrix.org"); room = new Room("!id", cli, "@alice:matrix.org");
jest.spyOn(cli, "getRoom").mockReturnValue(room); jest.spyOn(cli, "getRoom").mockReturnValue(room);

View file

@ -70,7 +70,7 @@ function mockClient({
users = [], users = [],
}: MockClientOptions = {}): MatrixClient { }: MockClientOptions = {}): MatrixClient {
stubClient(); stubClient();
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
MatrixClientPeg.getHomeserverName = jest.fn(() => homeserver); MatrixClientPeg.getHomeserverName = jest.fn(() => homeserver);
cli.getUserId = jest.fn(() => userId); cli.getUserId = jest.fn(() => userId);
cli.getHomeserverUrl = jest.fn(() => homeserver); cli.getHomeserverUrl = jest.fn(() => homeserver);

View file

@ -31,7 +31,7 @@ describe("<RoomNotifications />", () => {
}); });
it("should render", () => { it("should render", () => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
const { asFragment } = render( const { asFragment } = render(
<MatrixClientContext.Provider value={cli}> <MatrixClientContext.Provider value={cli}>
<DevtoolsContext.Provider <DevtoolsContext.Provider

View file

@ -82,7 +82,7 @@ describe("AppTile", () => {
beforeAll(async () => { beforeAll(async () => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
cli.hasLazyLoadMembersEnabled = () => false; cli.hasLazyLoadMembersEnabled = () => false;
// Init misc. startup deps // Init misc. startup deps

View file

@ -274,7 +274,7 @@ describe("PollCreateDialog", () => {
}); });
function createRoom(): Room { function createRoom(): Room {
return new Room("roomid", MatrixClientPeg.get(), "@name:example.com", {}); return new Room("roomid", MatrixClientPeg.safeGet(), "@name:example.com", {});
} }
function changeValue(wrapper: RenderResult, labelText: string, value: string) { function changeValue(wrapper: RenderResult, labelText: string, value: string) {

View file

@ -58,7 +58,7 @@ describe("CallEvent", () => {
jest.setSystemTime(0); jest.setSystemTime(0);
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
client.getUserId.mockReturnValue("@alice:example.org"); client.getUserId.mockReturnValue("@alice:example.org");
room = new Room("!1:example.org", client, "@alice:example.org", { room = new Room("!1:example.org", client, "@alice:example.org", {

View file

@ -38,7 +38,7 @@ describe("<RoomPredecessorTile />", () => {
const userId = "@alice:server.org"; const userId = "@alice:server.org";
const roomId = "!room:server.org"; const roomId = "!room:server.org";
stubClient(); stubClient();
const client = mocked(MatrixClientPeg.get()); const client = mocked(MatrixClientPeg.safeGet());
function makeRoom({ function makeRoom({
createEventHasPredecessor = false, createEventHasPredecessor = false,
@ -165,7 +165,7 @@ describe("<RoomPredecessorTile />", () => {
filterConsole("Failed to find predecessor room with id old_room_id"); filterConsole("Failed to find predecessor room with id old_room_id");
beforeEach(() => { beforeEach(() => {
mocked(MatrixClientPeg.get().getRoom).mockReturnValue(null); mocked(MatrixClientPeg.safeGet().getRoom).mockReturnValue(null);
}); });
it("Shows an error if there are no via servers", () => { it("Shows an error if there are no via servers", () => {
@ -219,7 +219,7 @@ describe("<RoomPredecessorTile />", () => {
filterConsole("Failed to find predecessor room with id old_room_id"); filterConsole("Failed to find predecessor room with id old_room_id");
beforeEach(() => { beforeEach(() => {
mocked(MatrixClientPeg.get().getRoom).mockReturnValue(null); mocked(MatrixClientPeg.safeGet().getRoom).mockReturnValue(null);
}); });
it("Shows an error if there are no via servers", () => { it("Shows an error if there are no via servers", () => {

View file

@ -34,7 +34,7 @@ import { RoomPermalinkCreator } from "../../../../src/utils/permalinks/Permalink
describe("<PinnedMessagesCard />", () => { describe("<PinnedMessagesCard />", () => {
stubClient(); stubClient();
const cli = mocked(MatrixClientPeg.get()); const cli = mocked(MatrixClientPeg.safeGet());
cli.getUserId.mockReturnValue("@alice:example.org"); cli.getUserId.mockReturnValue("@alice:example.org");
cli.setRoomAccountData.mockResolvedValue({}); cli.setRoomAccountData.mockResolvedValue({});
cli.relations.mockResolvedValue({ originalEvent: {} as unknown as MatrixEvent, events: [] }); cli.relations.mockResolvedValue({ originalEvent: {} as unknown as MatrixEvent, events: [] });

View file

@ -35,7 +35,7 @@ describe("RoomHeaderButtons-test.tsx", function () {
jest.clearAllMocks(); jest.clearAllMocks();
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
client.supportsThreads = () => true; client.supportsThreads = () => true;
room = new Room(ROOM_ID, client, client.getUserId() ?? "", { room = new Room(ROOM_ID, client, client.getUserId() ?? "", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -32,7 +32,7 @@ describe("BasicMessageComposer", () => {
TestUtils.stubClient(); TestUtils.stubClient();
const client: MatrixClient = MatrixClientPeg.get(); const client: MatrixClient = MatrixClientPeg.safeGet();
const roomId = "!1234567890:domain"; const roomId = "!1234567890:domain";
const userId = client.getSafeUserId(); const userId = client.getSafeUserId();

View file

@ -73,7 +73,7 @@ describe("EventTile", () => {
jest.clearAllMocks(); jest.clearAllMocks();
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
room = new Room(ROOM_ID, client, client.getSafeUserId(), { room = new Room(ROOM_ID, client, client.getSafeUserId(), {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -143,7 +143,7 @@ describe("MemberList", () => {
describe.each([false, true])("does order members correctly (presence %s)", (enablePresence) => { describe.each([false, true])("does order members correctly (presence %s)", (enablePresence) => {
beforeEach(function () { beforeEach(function () {
TestUtils.stubClient(); TestUtils.stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
client.hasLazyLoadMembersEnabled = () => false; client.hasLazyLoadMembersEnabled = () => false;
// Make room // Make room

View file

@ -71,7 +71,7 @@ const startVoiceMessage = async (): Promise<void> => {
const setCurrentBroadcastRecording = (room: Room, state: VoiceBroadcastInfoState): void => { const setCurrentBroadcastRecording = (room: Room, state: VoiceBroadcastInfoState): void => {
const recording = new VoiceBroadcastRecording( const recording = new VoiceBroadcastRecording(
mkVoiceBroadcastInfoStateEvent(room.roomId, state, "@user:example.com", "ABC123"), mkVoiceBroadcastInfoStateEvent(room.roomId, state, "@user:example.com", "ABC123"),
MatrixClientPeg.get(), MatrixClientPeg.safeGet(),
state, state,
); );
SdkContextClass.instance.voiceBroadcastRecordingsStore.setCurrent(recording); SdkContextClass.instance.voiceBroadcastRecordingsStore.setCurrent(recording);
@ -483,7 +483,7 @@ function wrapAndRender(
narrow = false, narrow = false,
tombstone?: MatrixEvent, tombstone?: MatrixEvent,
) { ) {
const mockClient = MatrixClientPeg.get(); const mockClient = MatrixClientPeg.safeGet();
const roomId = "myroomid"; const roomId = "myroomid";
const room: any = props.room || { const room: any = props.room || {
currentState: undefined, currentState: undefined,

View file

@ -69,7 +69,7 @@ describe("RoomHeader", () => {
mockPlatformPeg({ supportsJitsiScreensharing: () => true }); mockPlatformPeg({ supportsJitsiScreensharing: () => true });
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
client.getUserId.mockReturnValue("@alice:example.org"); client.getUserId.mockReturnValue("@alice:example.org");
room = new Room("!1:example.org", client, "@alice:example.org", { room = new Room("!1:example.org", client, "@alice:example.org", {
@ -750,7 +750,7 @@ interface IRoomCreationInfo {
function createRoom(info: IRoomCreationInfo) { function createRoom(info: IRoomCreationInfo) {
stubClient(); stubClient();
const client: MatrixClient = MatrixClientPeg.get(); const client: MatrixClient = MatrixClientPeg.safeGet();
const roomId = "!1234567890:domain"; const roomId = "!1234567890:domain";
const userId = client.getUserId()!; const userId = client.getUserId()!;

View file

@ -47,7 +47,7 @@ DMRoomMap.sharedInstance = { getUserIdForRoomId, getDMRoomsForUserId };
describe("RoomList", () => { describe("RoomList", () => {
stubClient(); stubClient();
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
const store = SpaceStore.instance; const store = SpaceStore.instance;
function getComponent(props: Partial<ComponentProps<typeof RoomList>> = {}): JSX.Element { function getComponent(props: Partial<ComponentProps<typeof RoomList>> = {}): JSX.Element {

View file

@ -112,7 +112,7 @@ describe("RoomListHeader", () => {
} as unknown as DMRoomMap; } as unknown as DMRoomMap;
DMRoomMap.setShared(dmRoomMap); DMRoomMap.setShared(dmRoomMap);
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
mocked(shouldShowComponent).mockReturnValue(true); // show all UIComponents mocked(shouldShowComponent).mockReturnValue(true); // show all UIComponents
}); });

View file

@ -33,7 +33,7 @@ jest.mock("../../../../src/IdentityAuthClient", () => {
jest.useRealTimers(); jest.useRealTimers();
const createRoom = (roomId: string, userId: string): Room => { const createRoom = (roomId: string, userId: string): Room => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
const newRoom = new Room(roomId, cli, userId, {}); const newRoom = new Room(roomId, cli, userId, {});
DMRoomMap.makeShared(cli).start(); DMRoomMap.makeShared(cli).start();
return newRoom; return newRoom;
@ -92,7 +92,7 @@ describe("<RoomPreviewBar />", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
MatrixClientPeg.get().getUserId = jest.fn().mockReturnValue(userId); MatrixClientPeg.safeGet().getUserId = jest.fn().mockReturnValue(userId);
}); });
afterEach(() => { afterEach(() => {
@ -118,7 +118,7 @@ describe("<RoomPreviewBar />", () => {
}); });
it("renders not logged in message", () => { it("renders not logged in message", () => {
MatrixClientPeg.get().isGuest = jest.fn().mockReturnValue(true); MatrixClientPeg.safeGet().isGuest = jest.fn().mockReturnValue(true);
const component = getComponent({ loading: true }); const component = getComponent({ loading: true });
expect(isSpinnerRendered(component)).toBeFalsy(); expect(isSpinnerRendered(component)).toBeFalsy();
@ -126,7 +126,7 @@ describe("<RoomPreviewBar />", () => {
}); });
it("should send room oob data to start login", async () => { it("should send room oob data to start login", async () => {
MatrixClientPeg.get().isGuest = jest.fn().mockReturnValue(true); MatrixClientPeg.safeGet().isGuest = jest.fn().mockReturnValue(true);
const component = getComponent({ const component = getComponent({
oobData: { oobData: {
name: "Room Name", name: "Room Name",
@ -339,7 +339,7 @@ describe("<RoomPreviewBar />", () => {
describe("when client fails to get 3PIDs", () => { describe("when client fails to get 3PIDs", () => {
beforeEach(() => { beforeEach(() => {
MatrixClientPeg.get().getThreePids = jest.fn().mockRejectedValue({ errCode: "TEST_ERROR" }); MatrixClientPeg.safeGet().getThreePids = jest.fn().mockRejectedValue({ errCode: "TEST_ERROR" });
}); });
it("renders error message", async () => { it("renders error message", async () => {
@ -354,7 +354,7 @@ describe("<RoomPreviewBar />", () => {
describe("when invitedEmail is not associated with current account", () => { describe("when invitedEmail is not associated with current account", () => {
beforeEach(() => { beforeEach(() => {
MatrixClientPeg.get().getThreePids = jest MatrixClientPeg.safeGet().getThreePids = jest
.fn() .fn()
.mockResolvedValue({ threepids: mockThreePids.slice(1) }); .mockResolvedValue({ threepids: mockThreePids.slice(1) });
}); });
@ -371,8 +371,8 @@ describe("<RoomPreviewBar />", () => {
describe("when client has no identity server connected", () => { describe("when client has no identity server connected", () => {
beforeEach(() => { beforeEach(() => {
MatrixClientPeg.get().getThreePids = jest.fn().mockResolvedValue({ threepids: mockThreePids }); MatrixClientPeg.safeGet().getThreePids = jest.fn().mockResolvedValue({ threepids: mockThreePids });
MatrixClientPeg.get().getIdentityServerUrl = jest.fn().mockReturnValue(false); MatrixClientPeg.safeGet().getIdentityServerUrl = jest.fn().mockReturnValue(false);
}); });
it("renders invite message with invited email", async () => { it("renders invite message with invited email", async () => {
@ -387,18 +387,18 @@ describe("<RoomPreviewBar />", () => {
describe("when client has an identity server connected", () => { describe("when client has an identity server connected", () => {
beforeEach(() => { beforeEach(() => {
MatrixClientPeg.get().getThreePids = jest.fn().mockResolvedValue({ threepids: mockThreePids }); MatrixClientPeg.safeGet().getThreePids = jest.fn().mockResolvedValue({ threepids: mockThreePids });
MatrixClientPeg.get().getIdentityServerUrl = jest.fn().mockReturnValue("identity.test"); MatrixClientPeg.safeGet().getIdentityServerUrl = jest.fn().mockReturnValue("identity.test");
MatrixClientPeg.get().lookupThreePid = jest.fn().mockResolvedValue("identity.test"); MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockResolvedValue("identity.test");
}); });
it("renders email mismatch message when invite email mxid doesnt match", async () => { it("renders email mismatch message when invite email mxid doesnt match", async () => {
MatrixClientPeg.get().lookupThreePid = jest.fn().mockReturnValue("not userid"); MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockReturnValue("not userid");
const component = getComponent({ inviterName, invitedEmail }); const component = getComponent({ inviterName, invitedEmail });
await new Promise(setImmediate); await new Promise(setImmediate);
expect(getMessage(component)).toMatchSnapshot(); expect(getMessage(component)).toMatchSnapshot();
expect(MatrixClientPeg.get().lookupThreePid).toHaveBeenCalledWith( expect(MatrixClientPeg.safeGet().lookupThreePid).toHaveBeenCalledWith(
"email", "email",
invitedEmail, invitedEmail,
"mock-token", "mock-token",
@ -407,7 +407,7 @@ describe("<RoomPreviewBar />", () => {
}); });
it("renders invite message when invite email mxid match", async () => { it("renders invite message when invite email mxid match", async () => {
MatrixClientPeg.get().lookupThreePid = jest.fn().mockReturnValue(userId); MatrixClientPeg.safeGet().lookupThreePid = jest.fn().mockReturnValue(userId);
const component = getComponent({ inviterName, invitedEmail }); const component = getComponent({ inviterName, invitedEmail });
await new Promise(setImmediate); await new Promise(setImmediate);

View file

@ -40,7 +40,7 @@ describe("RoomPreviewCard", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
client.getUserId.mockReturnValue("@alice:example.org"); client.getUserId.mockReturnValue("@alice:example.org");
DMRoomMap.makeShared(client); DMRoomMap.makeShared(client);

View file

@ -31,7 +31,7 @@ type Props = React.ComponentPropsWithoutRef<typeof SearchResultTile>;
describe("SearchResultTile", () => { describe("SearchResultTile", () => {
beforeAll(() => { beforeAll(() => {
stubClient(); stubClient();
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
const room = new Room(ROOM_ID, cli, "@bob:example.org"); const room = new Room(ROOM_ID, cli, "@bob:example.org");
jest.spyOn(cli, "getRoom").mockReturnValue(room); jest.spyOn(cli, "getRoom").mockReturnValue(room);

View file

@ -56,6 +56,7 @@ describe("<VoiceRecordComposerTile/>", () => {
sendMessage: jest.fn(), sendMessage: jest.fn(),
} as unknown as MatrixClient; } as unknown as MatrixClient;
MatrixClientPeg.get = () => mockClient; MatrixClientPeg.get = () => mockClient;
MatrixClientPeg.safeGet = () => mockClient;
const room = { const room = {
roomId, roomId,

View file

@ -29,7 +29,7 @@ describe("CryptographyPanel", () => {
const sessionKeyFormatted = "<b>AbCD eFgh IJK7 L/m4 nOPq RSTU VW4x yzaB CDef 6gHI Jkl</b>"; const sessionKeyFormatted = "<b>AbCD eFgh IJK7 L/m4 nOPq RSTU VW4x yzaB CDef 6gHI Jkl</b>";
TestUtils.stubClient(); TestUtils.stubClient();
const client: MatrixClient = MatrixClientPeg.get(); const client: MatrixClient = MatrixClientPeg.safeGet();
client.deviceId = sessionId; client.deviceId = sessionId;
client.getDeviceEd25519Key = () => sessionKey; client.getDeviceEd25519Key = () => sessionKey;

View file

@ -41,7 +41,7 @@ describe("AdvancedRoomSettingsTab", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
room = mkStubRoom(roomId, "test room", cli); room = mkStubRoom(roomId, "test room", cli);
mocked(cli.getRoom).mockReturnValue(room); mocked(cli.getRoom).mockReturnValue(room);
mocked(dis.dispatch).mockReset(); mocked(dis.dispatch).mockReset();

View file

@ -38,7 +38,7 @@ describe("NotificatinSettingsTab", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
const room = mkStubRoom(roomId, "test room", cli); const room = mkStubRoom(roomId, "test room", cli);
roomProps = EchoChamber.forRoom(room); roomProps = EchoChamber.forRoom(room);

View file

@ -50,7 +50,7 @@ describe("RolesRoomSettingsTab", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
room = mkStubRoom(roomId, "test room", cli); room = mkStubRoom(roomId, "test room", cli);
}); });

View file

@ -38,7 +38,7 @@ describe("VoipRoomSettingsTab", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
room = mkStubRoom(roomId, "test room", cli); room = mkStubRoom(roomId, "test room", cli);
jest.spyOn(cli, "sendStateEvent"); jest.spyOn(cli, "sendStateEvent");

View file

@ -53,7 +53,7 @@ describe("PreferencesUserSettingsTab", () => {
const getToggle = () => renderTab().getByRole("switch", { name: "Send read receipts" }); const getToggle = () => renderTab().getByRole("switch", { name: "Send read receipts" });
const mockIsVersionSupported = (val: boolean) => { const mockIsVersionSupported = (val: boolean) => {
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
jest.spyOn(client, "doesServerSupportUnstableFeature").mockResolvedValue(false); jest.spyOn(client, "doesServerSupportUnstableFeature").mockResolvedValue(false);
jest.spyOn(client, "isVersionSupported").mockImplementation(async (version: string) => { jest.spyOn(client, "isVersionSupported").mockImplementation(async (version: string) => {
if (version === "v1.4") return val; if (version === "v1.4") return val;

View file

@ -107,6 +107,7 @@ describe("<SpaceSettingsVisibilityTab />", () => {
(mockMatrixClient.sendStateEvent as jest.Mock).mockClear().mockResolvedValue({}); (mockMatrixClient.sendStateEvent as jest.Mock).mockClear().mockResolvedValue({});
MatrixClientPeg.get = jest.fn().mockReturnValue(mockMatrixClient); MatrixClientPeg.get = jest.fn().mockReturnValue(mockMatrixClient);
MatrixClientPeg.safeGet = jest.fn().mockReturnValue(mockMatrixClient);
}); });
afterEach(() => { afterEach(() => {

View file

@ -39,8 +39,8 @@ jest.mock("../../../../src/stores/spaces/SpaceStore", () => {
describe("SpaceButton", () => { describe("SpaceButton", () => {
stubClient(); stubClient();
const space = mkRoom(MatrixClientPeg.get(), "!1:example.org"); const space = mkRoom(MatrixClientPeg.safeGet(), "!1:example.org");
DMRoomMap.makeShared(MatrixClientPeg.get()); DMRoomMap.makeShared(MatrixClientPeg.safeGet());
const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch"); const dispatchSpy = jest.spyOn(defaultDispatcher, "dispatch");

View file

@ -54,7 +54,7 @@ describe("CallLobby", () => {
mocked(navigator.mediaDevices.enumerateDevices).mockResolvedValue([]); mocked(navigator.mediaDevices.enumerateDevices).mockResolvedValue([]);
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
room = new Room("!1:example.org", client, "@alice:example.org", { room = new Room("!1:example.org", client, "@alice:example.org", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -32,7 +32,7 @@ describe("createRoom", () => {
let client: Mocked<MatrixClient>; let client: Mocked<MatrixClient>;
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
}); });
afterEach(() => jest.clearAllMocks()); afterEach(() => jest.clearAllMocks());

View file

@ -31,7 +31,7 @@ describe("useProfileInfo", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
cli.getProfileInfo = (query) => { cli.getProfileInfo = (query) => {
return Promise.resolve({ return Promise.resolve({
avatar_url: undefined, avatar_url: undefined,

View file

@ -31,7 +31,7 @@ describe("usePublicRoomDirectory", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
MatrixClientPeg.getHomeserverName = () => "matrix.org"; MatrixClientPeg.getHomeserverName = () => "matrix.org";
cli.getThirdpartyProtocols = () => Promise.resolve({}); cli.getThirdpartyProtocols = () => Promise.resolve({});

View file

@ -31,7 +31,7 @@ describe("useUserDirectory", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
MatrixClientPeg.getHomeserverName = () => "matrix.org"; MatrixClientPeg.getHomeserverName = () => "matrix.org";
cli.getThirdpartyProtocols = () => Promise.resolve({}); cli.getThirdpartyProtocols = () => Promise.resolve({});

View file

@ -68,7 +68,7 @@ const setUpClientRoomAndStores = (): {
carol: RoomMember; carol: RoomMember;
} => { } => {
stubClient(); stubClient();
const client = mocked<MatrixClient>(MatrixClientPeg.get()); const client = mocked<MatrixClient>(MatrixClientPeg.safeGet());
const room = new Room("!1:example.org", client, "@alice:example.org", { const room = new Room("!1:example.org", client, "@alice:example.org", {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -66,6 +66,7 @@ describe("DeviceSettingsHandler", () => {
afterEach(() => { afterEach(() => {
MatrixClientPeg.get = () => null; MatrixClientPeg.get = () => null;
MatrixClientPeg.safeGet = () => null;
}); });
it("Returns the value for a disabled feature", () => { it("Returns the value for a disabled feature", () => {

View file

@ -93,7 +93,7 @@ DMRoomMap.sharedInstance = { getUserIdForRoomId, getDMRoomsForUserId };
describe("SpaceStore", () => { describe("SpaceStore", () => {
stubClient(); stubClient();
const store = SpaceStore.instance; const store = SpaceStore.instance;
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.safeGet();
const spyDispatcher = jest.spyOn(defaultDispatcher, "dispatch"); const spyDispatcher = jest.spyOn(defaultDispatcher, "dispatch");

View file

@ -36,7 +36,7 @@ describe("RightPanelStore", () => {
let cli: MockedObject<MatrixClient>; let cli: MockedObject<MatrixClient>;
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = mocked(MatrixClientPeg.get()); cli = mocked(MatrixClientPeg.safeGet());
DMRoomMap.makeShared(cli); DMRoomMap.makeShared(cli);
// Make sure we start with a clean store // Make sure we start with a clean store

View file

@ -49,7 +49,7 @@ const space2 = "!space2:server";
describe("SpaceWatcher", () => { describe("SpaceWatcher", () => {
stubClient(); stubClient();
const store = SpaceStore.instance; const store = SpaceStore.instance;
const client = mocked(MatrixClientPeg.get()); const client = mocked(MatrixClientPeg.safeGet());
let rooms: Room[] = []; let rooms: Room[] = [];
const mkSpaceForRooms = (spaceId: string, children: string[] = []) => mkSpace(client, spaceId, rooms, children); const mkSpaceForRooms = (spaceId: string, children: string[] = []) => mkSpace(client, spaceId, rooms, children);

View file

@ -40,7 +40,7 @@ describe("Algorithm", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
DMRoomMap.makeShared(client); DMRoomMap.makeShared(client);
algorithm = new Algorithm(); algorithm = new Algorithm();

View file

@ -31,7 +31,7 @@ describe("RecentAlgorithm", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
cli = MatrixClientPeg.get(); cli = MatrixClientPeg.safeGet();
algorithm = new RecentAlgorithm(); algorithm = new RecentAlgorithm();
}); });

View file

@ -60,7 +60,7 @@ describe("ReactionEventPreview", () => {
}); });
it("should use 'You' for your own reactions", () => { it("should use 'You' for your own reactions", () => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
const room = new Room(roomId, cli, userId); const room = new Room(roomId, cli, userId);
mocked(cli.getRoom).mockReturnValue(room); mocked(cli.getRoom).mockReturnValue(room);
@ -97,7 +97,7 @@ describe("ReactionEventPreview", () => {
}); });
it("should use display name for your others' reactions", () => { it("should use display name for your others' reactions", () => {
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
const room = new Room(roomId, cli, userId); const room = new Room(roomId, cli, userId);
mocked(cli.getRoom).mockReturnValue(room); mocked(cli.getRoom).mockReturnValue(room);

View file

@ -36,7 +36,7 @@ describe("StopGapWidget", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
widget = new StopGapWidget({ widget = new StopGapWidget({
app: { app: {

View file

@ -61,7 +61,7 @@ describe("StopGapWidgetDriver", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
client.getUserId.mockReturnValue("@alice:example.org"); client.getUserId.mockReturnValue("@alice:example.org");
}); });

View file

@ -71,6 +71,7 @@ export const getMockClientWithEventEmitter = (
const mock = mocked(new MockClientWithEventEmitter(mockProperties) as unknown as MatrixClient); const mock = mocked(new MockClientWithEventEmitter(mockProperties) as unknown as MatrixClient);
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mock); jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mock);
jest.spyOn(MatrixClientPeg, "safeGet").mockReturnValue(mock);
// @ts-ignore simplified test stub // @ts-ignore simplified test stub
mock.canSupport = new Map(); mock.canSupport = new Map();
@ -80,7 +81,10 @@ export const getMockClientWithEventEmitter = (
return mock; return mock;
}; };
export const unmockClientPeg = () => jest.spyOn(MatrixClientPeg, "get").mockRestore(); export const unmockClientPeg = () => {
jest.spyOn(MatrixClientPeg, "get").mockRestore();
jest.spyOn(MatrixClientPeg, "safeGet").mockRestore();
};
/** /**
* Returns basic mocked client methods related to the current user * Returns basic mocked client methods related to the current user

View file

@ -69,13 +69,13 @@ export function stubClient(): MatrixClient {
// 'sandbox.restore()' doesn't work correctly on inherited methods, // 'sandbox.restore()' doesn't work correctly on inherited methods,
// so we do this for each method // so we do this for each method
jest.spyOn(peg, "get"); jest.spyOn(peg, "get");
jest.spyOn(peg, "safeGet");
jest.spyOn(peg, "unset"); jest.spyOn(peg, "unset");
jest.spyOn(peg, "replaceUsingCreds"); jest.spyOn(peg, "replaceUsingCreds");
// MatrixClientPeg.get() is called a /lot/, so implement it with our own // MatrixClientPeg.safeGet() is called a /lot/, so implement it with our own
// fast stub function rather than a sinon stub // fast stub function rather than a sinon stub
peg.get = function () { peg.get = () => client;
return client; peg.safeGet = () => client;
};
MatrixClientBackedSettingsHandler.matrixClient = client; MatrixClientBackedSettingsHandler.matrixClient = client;
return client; return client;
} }

View file

@ -29,7 +29,7 @@ export function wrapInMatrixClientContext<T>(WrappedComponent: ComponentType<T>)
constructor(props: WrapperProps<T>) { constructor(props: WrapperProps<T>) {
super(props); super(props);
this._matrixClient = peg.get(); this._matrixClient = peg.safeGet();
} }
render() { render() {

View file

@ -60,7 +60,7 @@ describe("IncomingCallEvent", () => {
beforeEach(async () => { beforeEach(async () => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
room = new Room("!1:example.org", client, "@alice:example.org"); room = new Room("!1:example.org", client, "@alice:example.org");

View file

@ -25,7 +25,7 @@ import { MatrixClientPeg } from "../src/MatrixClientPeg";
describe("useTopic", () => { describe("useTopic", () => {
it("should display the room topic", () => { it("should display the room topic", () => {
stubClient(); stubClient();
const room = new Room("!TESTROOM", MatrixClientPeg.get(), "@alice:example.org"); const room = new Room("!TESTROOM", MatrixClientPeg.safeGet(), "@alice:example.org");
const topic = mkEvent({ const topic = mkEvent({
type: "m.room.topic", type: "m.room.topic",
room: "!TESTROOM", room: "!TESTROOM",

View file

@ -430,7 +430,7 @@ describe("EventUtils", () => {
jest.clearAllMocks(); jest.clearAllMocks();
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
room = new Room(ROOM_ID, client, client.getUserId()!, { room = new Room(ROOM_ID, client, client.getUserId()!, {
pendingEventOrdering: PendingEventOrdering.Detached, pendingEventOrdering: PendingEventOrdering.Detached,

View file

@ -80,7 +80,7 @@ describe("MultiInviter", () => {
jest.resetAllMocks(); jest.resetAllMocks();
TestUtilsMatrix.stubClient(); TestUtilsMatrix.stubClient();
client = MatrixClientPeg.get() as jest.Mocked<MatrixClient>; client = MatrixClientPeg.safeGet() as jest.Mocked<MatrixClient>;
client.invite = jest.fn(); client.invite = jest.fn();
client.invite.mockResolvedValue({}); client.invite.mockResolvedValue({});

View file

@ -53,7 +53,7 @@ describe("export", function () {
let events: MatrixEvent[]; let events: MatrixEvent[];
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = MatrixClientPeg.get(); client = MatrixClientPeg.safeGet();
client.getUserId = () => { client.getUserId = () => {
return MY_USER_ID; return MY_USER_ID;
}; };

View file

@ -40,7 +40,7 @@ describe("leaveRoomBehaviour", () => {
beforeEach(async () => { beforeEach(async () => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
DMRoomMap.makeShared(client); DMRoomMap.makeShared(client);
room = mkRoom(client, "!1:example.org"); room = mkRoom(client, "!1:example.org");

View file

@ -119,7 +119,7 @@ describe("notifications", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
room = new Room(ROOM_ID, client, USER_ID); room = new Room(ROOM_ID, client, USER_ID);
message = mkMessage({ message = mkMessage({
event: true, event: true,
@ -172,7 +172,7 @@ describe("notifications", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
client = mocked(MatrixClientPeg.get()); client = mocked(MatrixClientPeg.safeGet());
room = new Room(ROOM_ID, client, USER_ID); room = new Room(ROOM_ID, client, USER_ID);
sendReadReceiptSpy = jest.spyOn(client, "sendReadReceipt").mockResolvedValue({}); sendReadReceiptSpy = jest.spyOn(client, "sendReadReceipt").mockResolvedValue({});
jest.spyOn(client, "getRooms").mockReturnValue([room]); jest.spyOn(client, "getRooms").mockReturnValue([room]);

View file

@ -36,7 +36,7 @@ describe("pillify", () => {
beforeEach(() => { beforeEach(() => {
stubClient(); stubClient();
const cli = MatrixClientPeg.get(); const cli = MatrixClientPeg.safeGet();
(cli.getRoom as jest.Mock).mockReturnValue(new Room(roomId, cli, cli.getUserId()!)); (cli.getRoom as jest.Mock).mockReturnValue(new Room(roomId, cli, cli.getUserId()!));
cli.pushRules!.global = { cli.pushRules!.global = {
override: [ override: [
@ -69,7 +69,7 @@ describe("pillify", () => {
const { container } = render(<div />); const { container } = render(<div />);
const originalHtml = container.outerHTML; const originalHtml = container.outerHTML;
const containers: Element[] = []; const containers: Element[] = [];
pillifyLinks(MatrixClientPeg.get(), [container], event, containers); pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
expect(containers).toHaveLength(0); expect(containers).toHaveLength(0);
expect(container.outerHTML).toEqual(originalHtml); expect(container.outerHTML).toEqual(originalHtml);
}); });
@ -77,7 +77,7 @@ describe("pillify", () => {
it("should pillify @room", () => { it("should pillify @room", () => {
const { container } = render(<div>@room</div>); const { container } = render(<div>@room</div>);
const containers: Element[] = []; const containers: Element[] = [];
pillifyLinks(MatrixClientPeg.get(), [container], event, containers); pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
expect(containers).toHaveLength(1); expect(containers).toHaveLength(1);
expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room"); expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room");
}); });
@ -85,10 +85,10 @@ describe("pillify", () => {
it("should not double up pillification on repeated calls", () => { it("should not double up pillification on repeated calls", () => {
const { container } = render(<div>@room</div>); const { container } = render(<div>@room</div>);
const containers: Element[] = []; const containers: Element[] = [];
pillifyLinks(MatrixClientPeg.get(), [container], event, containers); pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
pillifyLinks(MatrixClientPeg.get(), [container], event, containers); pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
pillifyLinks(MatrixClientPeg.get(), [container], event, containers); pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
pillifyLinks(MatrixClientPeg.get(), [container], event, containers); pillifyLinks(MatrixClientPeg.safeGet(), [container], event, containers);
expect(containers).toHaveLength(1); expect(containers).toHaveLength(1);
expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room"); expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room");
}); });

View file

@ -48,7 +48,7 @@ describe("textForVoiceBroadcastStoppedEvent", () => {
}; };
} }
return render(<div>{textForVoiceBroadcastStoppedEvent(event)()}</div>); return render(<div>{textForVoiceBroadcastStoppedEvent(event, client)()}</div>);
}; };
beforeEach(() => { beforeEach(() => {