mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-15 20:54:59 +08:00
Merge branch 'develop' into michaelk/continue_if_trci_upload_fails
This commit is contained in:
commit
e652519cc6
6
.github/workflows/cypress.yaml
vendored
6
.github/workflows/cypress.yaml
vendored
@ -92,6 +92,12 @@ jobs:
|
||||
# # Run 4 instances in Parallel
|
||||
# runner: [1, 2, 3, 4]
|
||||
steps:
|
||||
- uses: tecolicom/actions-use-apt-tools@v1
|
||||
with:
|
||||
# Our test suite includes some screenshot tests with unusual diacritics, which are
|
||||
# supposed to be covered by STIXGeneral.
|
||||
tools: fonts-stix
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# XXX: We're checking out untrusted code in a secure context
|
||||
|
@ -115,7 +115,10 @@ describe("Polls", () => {
|
||||
|
||||
const pollParams = {
|
||||
title: "Does the polls feature work?",
|
||||
options: ["Yes", "No", "Maybe"],
|
||||
// Since we're going to take a screenshot anyways, we include some
|
||||
// non-ASCII characters here to stress test the app's font config
|
||||
// while we're at it.
|
||||
options: ["Yes", "Noo⃐o⃑o⃩o⃪o⃫o⃬o⃭o⃮o⃯", "のらねこ Maybe?"],
|
||||
};
|
||||
createPoll(pollParams);
|
||||
|
||||
|
@ -4,17 +4,20 @@
|
||||
Arial empirically gets it right, hence prioritising Arial here.
|
||||
We also include STIXGeneral explicitly to support a wider range
|
||||
of combining diacritics (Chrome fails without it, as per
|
||||
https://bugs.chromium.org/p/chromium/issues/detail?id=1328898) */
|
||||
https://bugs.chromium.org/p/chromium/issues/detail?id=1328898).
|
||||
We should never actively *prefer* STIXGeneral over the default font though,
|
||||
since it looks pretty rough and implements some non-LGC scripts only
|
||||
partially, making, for example, Japanese text look patchy and sad. */
|
||||
/* We fall through to Twemoji for emoji rather than falling through
|
||||
to native Emoji fonts (if any) to ensure cross-browser consistency */
|
||||
/* Noto Color Emoji contains digits, in fixed-width, therefore causing
|
||||
digits in flowed text to stand out.
|
||||
TODO: Consider putting all emoji fonts to the end rather than the front. */
|
||||
$font-family: "Nunito", "Twemoji", "Apple Color Emoji", "Segoe UI Emoji", "STIXGeneral", "Arial", "Helvetica",
|
||||
sans-serif, "Noto Color Emoji";
|
||||
$font-family: "Nunito", "Twemoji", "Apple Color Emoji", "Segoe UI Emoji", "Arial", "Helvetica", sans-serif,
|
||||
"STIXGeneral", "Noto Color Emoji";
|
||||
|
||||
$monospace-font-family: "Inconsolata", "Twemoji", "Apple Color Emoji", "Segoe UI Emoji", "STIXGeneral", "Courier",
|
||||
monospace, "Noto Color Emoji";
|
||||
$monospace-font-family: "Inconsolata", "Twemoji", "Apple Color Emoji", "Segoe UI Emoji", "Courier", monospace,
|
||||
"STIXGeneral", "Noto Color Emoji";
|
||||
|
||||
/* unified palette */
|
||||
/* try to use these colors when possible */
|
||||
|
@ -4,17 +4,20 @@
|
||||
Arial empirically gets it right, hence prioritising Arial here.
|
||||
We also include STIXGeneral explicitly to support a wider range
|
||||
of combining diacritics (Chrome fails without it, as per
|
||||
https://bugs.chromium.org/p/chromium/issues/detail?id=1328898) */
|
||||
https://bugs.chromium.org/p/chromium/issues/detail?id=1328898).
|
||||
We should never actively *prefer* STIXGeneral over the default font though,
|
||||
since it looks pretty rough and implements some non-LGC scripts only
|
||||
partially, making, for example, Japanese text look patchy and sad. */
|
||||
/* We fall through to Twemoji for emoji rather than falling through
|
||||
to native Emoji fonts (if any) to ensure cross-browser consistency */
|
||||
/* Noto Color Emoji contains digits, in fixed-width, therefore causing
|
||||
digits in flowed text to stand out.
|
||||
TODO: Consider putting all emoji fonts to the end rather than the front. */
|
||||
$font-family: "Inter", "Twemoji", "Apple Color Emoji", "Segoe UI Emoji", "STIXGeneral", "Arial", "Helvetica", sans-serif,
|
||||
$font-family: "Inter", "Twemoji", "Apple Color Emoji", "Segoe UI Emoji", "Arial", "Helvetica", sans-serif, "STIXGeneral",
|
||||
"Noto Color Emoji";
|
||||
|
||||
$monospace-font-family: "Inconsolata", "Twemoji", "Apple Color Emoji", "Segoe UI Emoji", "STIXGeneral", "Courier",
|
||||
monospace, "Noto Color Emoji";
|
||||
$monospace-font-family: "Inconsolata", "Twemoji", "Apple Color Emoji", "Segoe UI Emoji", "Courier", monospace,
|
||||
"STIXGeneral", "Noto Color Emoji";
|
||||
|
||||
/* Colors from Figma Compound https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=559%3A120 */
|
||||
/* ******************** */
|
||||
|
@ -50,6 +50,7 @@ import { localNotificationsAreSilenced, createLocalNotificationSettingsIfNeeded
|
||||
import { getIncomingCallToastKey, IncomingCallToast } from "./toasts/IncomingCallToast";
|
||||
import ToastStore from "./stores/ToastStore";
|
||||
import { ElementCall } from "./models/Call";
|
||||
import { VoiceBroadcastChunkEventType } from "./voice-broadcast";
|
||||
|
||||
/*
|
||||
* Dispatches:
|
||||
@ -77,6 +78,13 @@ const msgTypeHandlers = {
|
||||
[M_LOCATION.altName]: (event: MatrixEvent) => {
|
||||
return TextForEvent.textForLocationEvent(event)();
|
||||
},
|
||||
[MsgType.Audio]: (event: MatrixEvent): string | null => {
|
||||
if (event.getContent()?.[VoiceBroadcastChunkEventType]) {
|
||||
// mute broadcast chunks
|
||||
return null;
|
||||
}
|
||||
return TextForEvent.textForEvent(event);
|
||||
},
|
||||
};
|
||||
|
||||
export const Notifier = {
|
||||
|
@ -29,6 +29,7 @@ import * as Avatar from "../../../Avatar";
|
||||
import DMRoomMap from "../../../utils/DMRoomMap";
|
||||
import { mediaFromMxc } from "../../../customisations/Media";
|
||||
import { IOOBData } from "../../../stores/ThreepidInviteStore";
|
||||
import { LocalRoom } from "../../../models/LocalRoom";
|
||||
|
||||
interface IProps extends Omit<ComponentProps<typeof BaseAvatar>, "name" | "idName" | "url" | "onClick"> {
|
||||
// Room may be left unset here, but if it is,
|
||||
@ -117,13 +118,26 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
|
||||
Modal.createDialog(ImageView, params, "mx_Dialog_lightbox", null, true);
|
||||
};
|
||||
|
||||
public render() {
|
||||
const { room, oobData, viewAvatarOnClick, onClick, className, ...otherProps } = this.props;
|
||||
private get roomIdName(): string | undefined {
|
||||
const room = this.props.room;
|
||||
|
||||
const roomName = room?.name ?? oobData.name;
|
||||
if (room) {
|
||||
const dmMapUserId = DMRoomMap.shared().getUserIdForRoomId(room.roomId);
|
||||
// If the room is a DM, we use the other user's ID for the color hash
|
||||
// in order to match the room avatar with their avatar
|
||||
const idName = room ? DMRoomMap.shared().getUserIdForRoomId(room.roomId) ?? room.roomId : oobData.roomId;
|
||||
if (dmMapUserId) return dmMapUserId;
|
||||
|
||||
if (room instanceof LocalRoom && room.targets.length === 1) {
|
||||
return room.targets[0].userId;
|
||||
}
|
||||
}
|
||||
|
||||
return this.props.room?.roomId || this.props.oobData?.roomId;
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { room, oobData, viewAvatarOnClick, onClick, className, ...otherProps } = this.props;
|
||||
const roomName = room?.name ?? oobData.name;
|
||||
|
||||
return (
|
||||
<BaseAvatar
|
||||
@ -132,7 +146,7 @@ export default class RoomAvatar extends React.Component<IProps, IState> {
|
||||
mx_RoomAvatar_isSpaceRoom: (room?.getType() ?? this.props.oobData?.roomType) === RoomType.Space,
|
||||
})}
|
||||
name={roomName}
|
||||
idName={idName}
|
||||
idName={this.roomIdName}
|
||||
urls={this.state.urls}
|
||||
onClick={viewAvatarOnClick && this.state.urls[0] ? this.onRoomAvatarClick : onClick}
|
||||
/>
|
||||
|
@ -642,7 +642,7 @@ export default class Notifications extends React.PureComponent<IProps, IState> {
|
||||
className="mx_UserNotifSettings_clearNotifsButton"
|
||||
data-testid="clear-notifications"
|
||||
>
|
||||
{_t("Clear notifications")}
|
||||
{_t("Mark all as read")}
|
||||
</AccessibleButton>
|
||||
);
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { EventType, MatrixClient, MatrixEvent, RelationType } from "matrix-js-sdk/src/matrix";
|
||||
import { Relations } from "matrix-js-sdk/src/models/relations";
|
||||
|
||||
import { VoiceBroadcastInfoEventType } from "../voice-broadcast";
|
||||
|
||||
export const getReferenceRelationsForEvent = (
|
||||
event: MatrixEvent,
|
||||
messageType: EventType | typeof VoiceBroadcastInfoEventType,
|
||||
client: MatrixClient,
|
||||
): Relations | undefined => {
|
||||
const room = client.getRoom(event.getRoomId());
|
||||
return room
|
||||
?.getUnfilteredTimelineSet()
|
||||
?.relations?.getChildEventsForEvent(event.getId(), RelationType.Reference, messageType);
|
||||
};
|
@ -16,4 +16,3 @@ limitations under the License.
|
||||
|
||||
export { getForwardableEvent } from "./forward/getForwardableEvent";
|
||||
export { getShareableLocationEvent } from "./location/getShareableLocationEvent";
|
||||
export * from "./getReferenceRelationsForEvent";
|
||||
|
@ -1419,7 +1419,7 @@
|
||||
"Enable desktop notifications for this session": "Enable desktop notifications for this session",
|
||||
"Show message in desktop notification": "Show message in desktop notification",
|
||||
"Enable audible notifications for this session": "Enable audible notifications for this session",
|
||||
"Clear notifications": "Clear notifications",
|
||||
"Mark all as read": "Mark all as read",
|
||||
"Keyword": "Keyword",
|
||||
"New keyword": "New keyword",
|
||||
"On": "On",
|
||||
@ -2126,7 +2126,6 @@
|
||||
"%(count)s reply|one": "%(count)s reply",
|
||||
"Open thread": "Open thread",
|
||||
"Jump to first unread message.": "Jump to first unread message.",
|
||||
"Mark all as read": "Mark all as read",
|
||||
"Unable to access your microphone": "Unable to access your microphone",
|
||||
"We were unable to access your microphone. Please check your browser settings and try again.": "We were unable to access your microphone. Please check your browser settings and try again.",
|
||||
"No microphone found": "No microphone found",
|
||||
|
@ -20,6 +20,7 @@ import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";
|
||||
import { IContent, MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { SyncState } from "matrix-js-sdk/src/sync";
|
||||
import { waitFor } from "@testing-library/react";
|
||||
import { EventType, MsgType } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import BasePlatform from "../src/BasePlatform";
|
||||
import { ElementCall } from "../src/models/Call";
|
||||
@ -39,6 +40,7 @@ import { mkThread } from "./test-utils/threads";
|
||||
import dis from "../src/dispatcher/dispatcher";
|
||||
import { ThreadPayload } from "../src/dispatcher/payloads/ThreadPayload";
|
||||
import { Action } from "../src/dispatcher/actions";
|
||||
import { VoiceBroadcastChunkEventType } from "../src/voice-broadcast";
|
||||
|
||||
jest.mock("../src/utils/notifications", () => ({
|
||||
// @ts-ignore
|
||||
@ -73,6 +75,22 @@ describe("Notifier", () => {
|
||||
});
|
||||
};
|
||||
|
||||
const mkAudioEvent = (broadcastChunk = false): MatrixEvent => {
|
||||
const chunkContent = broadcastChunk ? { [VoiceBroadcastChunkEventType]: {} } : {};
|
||||
|
||||
return mkEvent({
|
||||
event: true,
|
||||
type: EventType.RoomMessage,
|
||||
user: "@user:example.com",
|
||||
room: "!room:example.com",
|
||||
content: {
|
||||
...chunkContent,
|
||||
msgtype: MsgType.Audio,
|
||||
body: "test audio message",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
accountDataStore = {};
|
||||
mockClient = getMockClientWithEventEmitter({
|
||||
@ -94,11 +112,11 @@ describe("Notifier", () => {
|
||||
});
|
||||
|
||||
mockClient.pushRules = {
|
||||
global: undefined,
|
||||
global: {},
|
||||
};
|
||||
accountDataEventKey = getLocalNotificationAccountDataEventType(mockClient.deviceId);
|
||||
accountDataEventKey = getLocalNotificationAccountDataEventType(mockClient.deviceId!);
|
||||
|
||||
testRoom = new Room(roomId, mockClient, mockClient.getUserId());
|
||||
testRoom = new Room(roomId, mockClient, mockClient.getSafeUserId());
|
||||
|
||||
MockPlatform = mockPlatformPeg({
|
||||
supportsNotifications: jest.fn().mockReturnValue(true),
|
||||
@ -109,8 +127,10 @@ describe("Notifier", () => {
|
||||
|
||||
Notifier.isBodyEnabled = jest.fn().mockReturnValue(true);
|
||||
|
||||
mockClient.getRoom.mockImplementation((id) => {
|
||||
return id === roomId ? testRoom : new Room(id, mockClient, mockClient.getUserId());
|
||||
mockClient.getRoom.mockImplementation((id: string | undefined): Room | null => {
|
||||
if (id === roomId) return testRoom;
|
||||
if (id) return new Room(id, mockClient, mockClient.getSafeUserId());
|
||||
return null;
|
||||
});
|
||||
});
|
||||
|
||||
@ -256,6 +276,24 @@ describe("Notifier", () => {
|
||||
Notifier._displayPopupNotification(testEvent, testRoom);
|
||||
expect(MockPlatform.displayNotification).toHaveBeenCalledTimes(count);
|
||||
});
|
||||
|
||||
it("should display a notification for a voice message", () => {
|
||||
const audioEvent = mkAudioEvent();
|
||||
Notifier._displayPopupNotification(audioEvent, testRoom);
|
||||
expect(MockPlatform.displayNotification).toHaveBeenCalledWith(
|
||||
"@user:example.com (!room1:server)",
|
||||
"@user:example.com: test audio message",
|
||||
"data:image/png;base64,00",
|
||||
testRoom,
|
||||
audioEvent,
|
||||
);
|
||||
});
|
||||
|
||||
it("should not display a notification for a broadcast chunk", () => {
|
||||
const audioEvent = mkAudioEvent(true);
|
||||
Notifier._displayPopupNotification(audioEvent, testRoom);
|
||||
expect(MockPlatform.displayNotification).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("getSoundForRoom", () => {
|
||||
@ -448,7 +486,7 @@ describe("Notifier", () => {
|
||||
|
||||
dis.dispatch<ThreadPayload>({
|
||||
action: Action.ViewThread,
|
||||
thread_id: rootEvent.getId(),
|
||||
thread_id: rootEvent.getId()!,
|
||||
});
|
||||
|
||||
await waitFor(() => expect(SdkContextClass.instance.roomViewStore.getThreadId()).toBe(rootEvent.getId()));
|
||||
@ -456,6 +494,11 @@ describe("Notifier", () => {
|
||||
Notifier._evaluateEvent(events[1]);
|
||||
expect(Notifier._displayPopupNotification).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("should show a pop-up for an audio message", () => {
|
||||
Notifier._evaluateEvent(mkAudioEvent());
|
||||
expect(Notifier._displayPopupNotification).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("setPromptHidden", () => {
|
||||
|
@ -40,7 +40,6 @@ describe("<ForgotPassword>", () => {
|
||||
let onComplete: () => void;
|
||||
let onLoginClick: () => void;
|
||||
let renderResult: RenderResult;
|
||||
let restoreConsole: () => void;
|
||||
|
||||
const typeIntoField = async (label: string, value: string): Promise<void> => {
|
||||
await act(async () => {
|
||||
@ -63,14 +62,14 @@ describe("<ForgotPassword>", () => {
|
||||
});
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
restoreConsole = filterConsole(
|
||||
filterConsole(
|
||||
// not implemented by js-dom https://github.com/jsdom/jsdom/issues/1937
|
||||
"Not implemented: HTMLFormElement.prototype.requestSubmit",
|
||||
// not of interested for this test
|
||||
"Starting load of AsyncWrapper for modal",
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
client = stubClient();
|
||||
mocked(createClient).mockReturnValue(client);
|
||||
|
||||
@ -87,7 +86,6 @@ describe("<ForgotPassword>", () => {
|
||||
afterEach(() => {
|
||||
// clean up modals
|
||||
Modal.closeCurrentModal("force");
|
||||
restoreConsole?.();
|
||||
});
|
||||
|
||||
beforeAll(() => {
|
||||
|
78
test/components/views/avatars/RoomAvatar-test.tsx
Normal file
78
test/components/views/avatars/RoomAvatar-test.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { render } from "@testing-library/react";
|
||||
import { MatrixClient, Room } from "matrix-js-sdk/src/matrix";
|
||||
import { mocked } from "jest-mock";
|
||||
|
||||
import RoomAvatar from "../../../../src/components/views/avatars/RoomAvatar";
|
||||
import { filterConsole, stubClient } from "../../../test-utils";
|
||||
import DMRoomMap from "../../../../src/utils/DMRoomMap";
|
||||
import { LocalRoom } from "../../../../src/models/LocalRoom";
|
||||
import * as AvatarModule from "../../../../src/Avatar";
|
||||
import { DirectoryMember } from "../../../../src/utils/direct-messages";
|
||||
|
||||
describe("RoomAvatar", () => {
|
||||
let client: MatrixClient;
|
||||
|
||||
filterConsole(
|
||||
// unrelated for this test
|
||||
"Room !room:example.com does not have an m.room.create event",
|
||||
);
|
||||
|
||||
beforeAll(() => {
|
||||
client = stubClient();
|
||||
const dmRoomMap = new DMRoomMap(client);
|
||||
jest.spyOn(dmRoomMap, "getUserIdForRoomId");
|
||||
jest.spyOn(DMRoomMap, "shared").mockReturnValue(dmRoomMap);
|
||||
jest.spyOn(AvatarModule, "defaultAvatarUrlForString");
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mocked(DMRoomMap.shared().getUserIdForRoomId).mockReset();
|
||||
mocked(AvatarModule.defaultAvatarUrlForString).mockClear();
|
||||
});
|
||||
|
||||
it("should render as expected for a Room", () => {
|
||||
const room = new Room("!room:example.com", client, client.getSafeUserId());
|
||||
room.name = "test room";
|
||||
expect(render(<RoomAvatar room={room} />).container).toMatchSnapshot();
|
||||
expect(AvatarModule.defaultAvatarUrlForString).toHaveBeenCalledWith(room.roomId);
|
||||
});
|
||||
|
||||
it("should render as expected for a DM room", () => {
|
||||
const userId = "@dm_user@example.com";
|
||||
const room = new Room("!room:example.com", client, client.getSafeUserId());
|
||||
room.name = "DM room";
|
||||
mocked(DMRoomMap.shared().getUserIdForRoomId).mockReturnValue(userId);
|
||||
expect(render(<RoomAvatar room={room} />).container).toMatchSnapshot();
|
||||
expect(AvatarModule.defaultAvatarUrlForString).toHaveBeenCalledWith(userId);
|
||||
});
|
||||
|
||||
it("should render as expected for a LocalRoom", () => {
|
||||
const userId = "@local_room_user@example.com";
|
||||
const localRoom = new LocalRoom("!room:example.com", client, client.getSafeUserId());
|
||||
localRoom.name = "local test room";
|
||||
localRoom.targets.push(new DirectoryMember({ user_id: userId }));
|
||||
expect(render(<RoomAvatar room={localRoom} />).container).toMatchSnapshot();
|
||||
expect(AvatarModule.defaultAvatarUrlForString).toHaveBeenCalledWith(userId);
|
||||
});
|
||||
});
|
@ -0,0 +1,76 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`RoomAvatar should render as expected for a DM room 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 23.400000000000002px; width: 36px; line-height: 36px;"
|
||||
>
|
||||
D
|
||||
</span>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
data-testid="avatar-img"
|
||||
src="data:image/png;base64,00"
|
||||
style="width: 36px; height: 36px;"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`RoomAvatar should render as expected for a LocalRoom 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 23.400000000000002px; width: 36px; line-height: 36px;"
|
||||
>
|
||||
L
|
||||
</span>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
data-testid="avatar-img"
|
||||
src="data:image/png;base64,00"
|
||||
style="width: 36px; height: 36px;"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`RoomAvatar should render as expected for a Room 1`] = `
|
||||
<div>
|
||||
<span
|
||||
class="mx_BaseAvatar"
|
||||
role="presentation"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_initial"
|
||||
style="font-size: 23.400000000000002px; width: 36px; line-height: 36px;"
|
||||
>
|
||||
T
|
||||
</span>
|
||||
<img
|
||||
alt=""
|
||||
aria-hidden="true"
|
||||
class="mx_BaseAvatar_image"
|
||||
data-testid="avatar-img"
|
||||
src="data:image/png;base64,00"
|
||||
style="width: 36px; height: 36px;"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
`;
|
@ -75,20 +75,19 @@ describe("RoomTile", () => {
|
||||
};
|
||||
|
||||
let client: Mocked<MatrixClient>;
|
||||
let restoreConsole: () => void;
|
||||
let voiceBroadcastInfoEvent: MatrixEvent;
|
||||
let room: Room;
|
||||
let renderResult: RenderResult;
|
||||
let sdkContext: TestSdkContext;
|
||||
|
||||
beforeEach(() => {
|
||||
sdkContext = new TestSdkContext();
|
||||
|
||||
restoreConsole = filterConsole(
|
||||
filterConsole(
|
||||
// irrelevant for this test
|
||||
"Room !1:example.org does not have an m.room.create event",
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
sdkContext = new TestSdkContext();
|
||||
|
||||
client = mocked(stubClient());
|
||||
sdkContext.client = client;
|
||||
DMRoomMap.makeShared();
|
||||
@ -105,7 +104,6 @@ describe("RoomTile", () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
restoreConsole();
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
|
@ -33,8 +33,6 @@ jest.mock("../../../../src/components/structures/HomePage", () => ({
|
||||
}));
|
||||
|
||||
describe("UserOnboardingPage", () => {
|
||||
let restoreConsole: () => void;
|
||||
|
||||
const renderComponent = async (): Promise<RenderResult> => {
|
||||
const renderResult = render(<UserOnboardingPage />);
|
||||
await act(async () => {
|
||||
@ -43,12 +41,10 @@ describe("UserOnboardingPage", () => {
|
||||
return renderResult;
|
||||
};
|
||||
|
||||
beforeAll(() => {
|
||||
restoreConsole = filterConsole(
|
||||
filterConsole(
|
||||
// unrelated for this test
|
||||
"could not update user onboarding context",
|
||||
);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
@ -60,10 +56,6 @@ describe("UserOnboardingPage", () => {
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
restoreConsole();
|
||||
});
|
||||
|
||||
describe("when the user registered before the cutoff date", () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(MatrixClientPeg, "userRegisteredAfter").mockReturnValue(false);
|
||||
|
@ -92,6 +92,7 @@ export const unmockClientPeg = () => jest.spyOn(MatrixClientPeg, "get").mockRest
|
||||
*/
|
||||
export const mockClientMethodsUser = (userId = "@alice:domain") => ({
|
||||
getUserId: jest.fn().mockReturnValue(userId),
|
||||
getSafeUserId: jest.fn().mockReturnValue(userId),
|
||||
getUser: jest.fn().mockReturnValue(new User(userId)),
|
||||
isGuest: jest.fn().mockReturnValue(false),
|
||||
mxcUrlToHttp: jest.fn().mockReturnValue("mock-mxcUrlToHttp"),
|
||||
|
@ -16,6 +16,14 @@ limitations under the License.
|
||||
|
||||
type FilteredConsole = Pick<Console, "log" | "error" | "info" | "debug" | "warn">;
|
||||
|
||||
/**
|
||||
* Allows to filter out specific messages in console.*.
|
||||
* Call this from any describe block.
|
||||
* Automagically restores the original function by implementing an afterAll hook.
|
||||
*
|
||||
* @param ignoreList Messages to be filtered
|
||||
*/
|
||||
export const filterConsole = (...ignoreList: string[]): void => {
|
||||
const originalFunctions: FilteredConsole = {
|
||||
log: console.log,
|
||||
error: console.error,
|
||||
@ -24,13 +32,7 @@ const originalFunctions: FilteredConsole = {
|
||||
warn: console.warn,
|
||||
};
|
||||
|
||||
/**
|
||||
* Allows to filter out specific messages in console.*.
|
||||
*
|
||||
* @param ignoreList Messages to be filtered
|
||||
* @returns function to restore the console
|
||||
*/
|
||||
export const filterConsole = (...ignoreList: string[]): (() => void) => {
|
||||
beforeAll(() => {
|
||||
for (const [key, originalFunction] of Object.entries(originalFunctions)) {
|
||||
window.console[key as keyof FilteredConsole] = (...data: any[]) => {
|
||||
const message = data?.[0]?.message || data?.[0];
|
||||
@ -42,10 +44,11 @@ export const filterConsole = (...ignoreList: string[]): (() => void) => {
|
||||
originalFunction(...data);
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
afterAll(() => {
|
||||
for (const [key, originalFunction] of Object.entries(originalFunctions)) {
|
||||
window.console[key as keyof FilteredConsole] = originalFunction;
|
||||
}
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -62,7 +62,6 @@ describe("VoiceBroadcastRecordingPip", () => {
|
||||
let infoEvent: MatrixEvent;
|
||||
let recording: VoiceBroadcastRecording;
|
||||
let renderResult: RenderResult;
|
||||
let restoreConsole: () => void;
|
||||
|
||||
const renderPip = async (state: VoiceBroadcastInfoState) => {
|
||||
infoEvent = mkVoiceBroadcastInfoStateEvent(roomId, state, client.getUserId() || "", client.getDeviceId() || "");
|
||||
@ -85,6 +84,8 @@ describe("VoiceBroadcastRecordingPip", () => {
|
||||
});
|
||||
};
|
||||
|
||||
filterConsole("Starting load of AsyncWrapper for modal");
|
||||
|
||||
beforeAll(() => {
|
||||
client = stubClient();
|
||||
mocked(requestMediaPermissions).mockResolvedValue({
|
||||
@ -105,11 +106,6 @@ describe("VoiceBroadcastRecordingPip", () => {
|
||||
[MediaDeviceKindEnum.VideoInput]: [],
|
||||
});
|
||||
jest.spyOn(MediaDeviceHandler.instance, "setDevice").mockImplementation();
|
||||
restoreConsole = filterConsole("Starting load of AsyncWrapper for modal");
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
restoreConsole();
|
||||
});
|
||||
|
||||
describe("when rendering a started recording", () => {
|
||||
|
@ -35,10 +35,6 @@ import { flushPromises, stubClient } from "../../test-utils";
|
||||
import { createTestPlayback } from "../../test-utils/audio";
|
||||
import { mkVoiceBroadcastChunkEvent, mkVoiceBroadcastInfoStateEvent } from "../utils/test-utils";
|
||||
|
||||
jest.mock("../../../src/events/getReferenceRelationsForEvent", () => ({
|
||||
getReferenceRelationsForEvent: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../../../src/utils/MediaEventHelper", () => ({
|
||||
MediaEventHelper: jest.fn(),
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user