Merge remote-tracking branch 'origin/develop' into feat/add-message-edition-wysiwyg-composer
This commit is contained in:
commit
de86221c72
55 changed files with 1551 additions and 668 deletions
112
test/components/views/rooms/EventTile-test.tsx
Normal file
112
test/components/views/rooms/EventTile-test.tsx
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
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 { act, render } from "@testing-library/react";
|
||||
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
|
||||
import { MatrixEvent } from "matrix-js-sdk/src/models/event";
|
||||
import { NotificationCountType, Room } from "matrix-js-sdk/src/models/room";
|
||||
import React from "react";
|
||||
|
||||
import EventTile, { EventTileProps } from "../../../../src/components/views/rooms/EventTile";
|
||||
import RoomContext, { TimelineRenderingType } from "../../../../src/contexts/RoomContext";
|
||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||
import { getRoomContext, mkMessage, stubClient } from "../../../test-utils";
|
||||
import { mkThread } from "../../../test-utils/threads";
|
||||
|
||||
describe("EventTile", () => {
|
||||
const ROOM_ID = "!roomId:example.org";
|
||||
let mxEvent: MatrixEvent;
|
||||
let room: Room;
|
||||
let client: MatrixClient;
|
||||
// let changeEvent: (event: MatrixEvent) => void;
|
||||
|
||||
function TestEventTile(props: Partial<EventTileProps>) {
|
||||
// const [event] = useState(mxEvent);
|
||||
// Give a way for a test to update the event prop.
|
||||
// changeEvent = setEvent;
|
||||
|
||||
return <EventTile
|
||||
mxEvent={mxEvent}
|
||||
{...props}
|
||||
/>;
|
||||
}
|
||||
|
||||
function getComponent(
|
||||
overrides: Partial<EventTileProps> = {},
|
||||
renderingType: TimelineRenderingType = TimelineRenderingType.Room,
|
||||
) {
|
||||
const context = getRoomContext(room, {
|
||||
timelineRenderingType: renderingType,
|
||||
});
|
||||
return render(
|
||||
<RoomContext.Provider value={context}>
|
||||
<TestEventTile {...overrides} />
|
||||
</RoomContext.Provider>,
|
||||
);
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
stubClient();
|
||||
client = MatrixClientPeg.get();
|
||||
|
||||
room = new Room(ROOM_ID, client, client.getUserId(), {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
|
||||
jest.spyOn(client, "getRoom").mockReturnValue(room);
|
||||
|
||||
mxEvent = mkMessage({
|
||||
room: room.roomId,
|
||||
user: "@alice:example.org",
|
||||
msg: "Hello world!",
|
||||
event: true,
|
||||
});
|
||||
});
|
||||
|
||||
describe("EventTile renderingType: ThreadsList", () => {
|
||||
beforeEach(() => {
|
||||
const { rootEvent } = mkThread({
|
||||
room,
|
||||
client,
|
||||
authorId: "@alice:example.org",
|
||||
participantUserIds: ["@alice:example.org"],
|
||||
});
|
||||
mxEvent = rootEvent;
|
||||
});
|
||||
|
||||
it("shows an unread notification bage", () => {
|
||||
const { container } = getComponent({}, TimelineRenderingType.ThreadsList);
|
||||
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(0);
|
||||
|
||||
act(() => {
|
||||
room.setThreadUnreadNotificationCount(mxEvent.getId(), NotificationCountType.Total, 3);
|
||||
});
|
||||
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(1);
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge_highlighted")).toHaveLength(0);
|
||||
|
||||
act(() => {
|
||||
room.setThreadUnreadNotificationCount(mxEvent.getId(), NotificationCountType.Highlight, 1);
|
||||
});
|
||||
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge")).toHaveLength(1);
|
||||
expect(container.getElementsByClassName("mx_NotificationBadge_highlighted")).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
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 { fireEvent, render } from "@testing-library/react";
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
StatelessNotificationBadge,
|
||||
} from "../../../../../src/components/views/rooms/NotificationBadge/StatelessNotificationBadge";
|
||||
import { NotificationColor } from "../../../../../src/stores/notifications/NotificationColor";
|
||||
|
||||
describe("NotificationBadge", () => {
|
||||
describe("StatelessNotificationBadge", () => {
|
||||
it("lets you click it", () => {
|
||||
const cb = jest.fn();
|
||||
|
||||
const { container } = render(<StatelessNotificationBadge
|
||||
symbol=""
|
||||
color={NotificationColor.Red}
|
||||
count={5}
|
||||
onClick={cb}
|
||||
onMouseOver={cb}
|
||||
onMouseLeave={cb}
|
||||
/>);
|
||||
|
||||
fireEvent.click(container.firstChild);
|
||||
expect(cb).toHaveBeenCalledTimes(1);
|
||||
|
||||
fireEvent.mouseEnter(container.firstChild);
|
||||
expect(cb).toHaveBeenCalledTimes(2);
|
||||
|
||||
fireEvent.mouseLeave(container.firstChild);
|
||||
expect(cb).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
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 "jest-mock";
|
||||
import { screen, act, render } from "@testing-library/react";
|
||||
import { MatrixClient, PendingEventOrdering } from "matrix-js-sdk/src/client";
|
||||
import { NotificationCountType, Room } from "matrix-js-sdk/src/models/room";
|
||||
import { mocked } from "jest-mock";
|
||||
import { EventStatus } from "matrix-js-sdk/src/models/event-status";
|
||||
|
||||
import {
|
||||
UnreadNotificationBadge,
|
||||
} from "../../../../../src/components/views/rooms/NotificationBadge/UnreadNotificationBadge";
|
||||
import { mkMessage, stubClient } from "../../../../test-utils/test-utils";
|
||||
import { MatrixClientPeg } from "../../../../../src/MatrixClientPeg";
|
||||
import * as RoomNotifs from "../../../../../src/RoomNotifs";
|
||||
|
||||
jest.mock("../../../../../src/RoomNotifs");
|
||||
jest.mock('../../../../../src/RoomNotifs', () => ({
|
||||
...(jest.requireActual('../../../../../src/RoomNotifs') as Object),
|
||||
getRoomNotifsState: jest.fn(),
|
||||
}));
|
||||
|
||||
const ROOM_ID = "!roomId:example.org";
|
||||
let THREAD_ID;
|
||||
|
||||
describe("UnreadNotificationBadge", () => {
|
||||
let mockClient: MatrixClient;
|
||||
let room: Room;
|
||||
|
||||
function getComponent(threadId?: string) {
|
||||
return <UnreadNotificationBadge room={room} threadId={threadId} />;
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
|
||||
stubClient();
|
||||
mockClient = mocked(MatrixClientPeg.get());
|
||||
|
||||
room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", {
|
||||
pendingEventOrdering: PendingEventOrdering.Detached,
|
||||
});
|
||||
room.setUnreadNotificationCount(NotificationCountType.Total, 1);
|
||||
room.setUnreadNotificationCount(NotificationCountType.Highlight, 0);
|
||||
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 1);
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0);
|
||||
|
||||
jest.spyOn(RoomNotifs, "getRoomNotifsState").mockReturnValue(RoomNotifs.RoomNotifState.AllMessages);
|
||||
});
|
||||
|
||||
it("renders unread notification badge", () => {
|
||||
const { container } = render(getComponent());
|
||||
|
||||
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeTruthy();
|
||||
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeFalsy();
|
||||
|
||||
act(() => {
|
||||
room.setUnreadNotificationCount(NotificationCountType.Highlight, 1);
|
||||
});
|
||||
|
||||
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("renders unread thread notification badge", () => {
|
||||
const { container } = render(getComponent(THREAD_ID));
|
||||
|
||||
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeTruthy();
|
||||
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeFalsy();
|
||||
|
||||
act(() => {
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 1);
|
||||
});
|
||||
|
||||
expect(container.querySelector(".mx_NotificationBadge_highlighted")).toBeTruthy();
|
||||
});
|
||||
|
||||
it("hides unread notification badge", () => {
|
||||
act(() => {
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Total, 0);
|
||||
room.setThreadUnreadNotificationCount(THREAD_ID, NotificationCountType.Highlight, 0);
|
||||
const { container } = render(getComponent(THREAD_ID));
|
||||
expect(container.querySelector(".mx_NotificationBadge_visible")).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it("adds a warning for unsent messages", () => {
|
||||
const evt = mkMessage({
|
||||
room: room.roomId,
|
||||
user: "@alice:example.org",
|
||||
msg: "Hello world!",
|
||||
event: true,
|
||||
});
|
||||
evt.status = EventStatus.NOT_SENT;
|
||||
|
||||
room.addPendingEvent(evt, "123");
|
||||
|
||||
render(getComponent());
|
||||
|
||||
expect(screen.queryByText("!")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("adds a warning for invites", () => {
|
||||
jest.spyOn(room, "getMyMembership").mockReturnValue("invite");
|
||||
render(getComponent());
|
||||
expect(screen.queryByText("!")).not.toBeNull();
|
||||
});
|
||||
|
||||
it("hides counter for muted rooms", () => {
|
||||
jest.spyOn(RoomNotifs, "getRoomNotifsState")
|
||||
.mockReset()
|
||||
.mockReturnValue(RoomNotifs.RoomNotifState.Mute);
|
||||
|
||||
const { container } = render(getComponent());
|
||||
expect(container.querySelector(".mx_NotificationBadge")).toBeNull();
|
||||
});
|
||||
});
|
|
@ -15,18 +15,14 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
renderIntoDocument,
|
||||
Simulate,
|
||||
findRenderedDOMComponentWithClass,
|
||||
act,
|
||||
} from 'react-dom/test-utils';
|
||||
import { render, fireEvent, RenderResult, waitFor } from "@testing-library/react";
|
||||
import { Room, RoomMember, MatrixError, IContent } from 'matrix-js-sdk/src/matrix';
|
||||
|
||||
import { stubClient } from '../../../test-utils';
|
||||
import { MatrixClientPeg } from '../../../../src/MatrixClientPeg';
|
||||
import DMRoomMap from '../../../../src/utils/DMRoomMap';
|
||||
import RoomPreviewBar from '../../../../src/components/views/rooms/RoomPreviewBar';
|
||||
import defaultDispatcher from "../../../../src/dispatcher/dispatcher";
|
||||
|
||||
jest.mock('../../../../src/IdentityAuthClient', () => {
|
||||
return jest.fn().mockImplementation(() => {
|
||||
|
@ -79,19 +75,18 @@ describe('<RoomPreviewBar />', () => {
|
|||
const defaultProps = {
|
||||
room: createRoom(roomId, userId),
|
||||
};
|
||||
const wrapper = renderIntoDocument<React.Component>(
|
||||
<RoomPreviewBar {...defaultProps} {...props} />,
|
||||
) as React.Component;
|
||||
return findRenderedDOMComponentWithClass(wrapper, 'mx_RoomPreviewBar') as HTMLDivElement;
|
||||
return render(<RoomPreviewBar {...defaultProps} {...props} />);
|
||||
};
|
||||
|
||||
const isSpinnerRendered = (element: Element) => !!element.querySelector('.mx_Spinner');
|
||||
const getMessage = (element: Element) => element.querySelector<HTMLDivElement>('.mx_RoomPreviewBar_message');
|
||||
const getActions = (element: Element) => element.querySelector<HTMLDivElement>('.mx_RoomPreviewBar_actions');
|
||||
const getPrimaryActionButton = (element: Element) =>
|
||||
getActions(element).querySelector('.mx_AccessibleButton_kind_primary');
|
||||
const getSecondaryActionButton = (element: Element) =>
|
||||
getActions(element).querySelector('.mx_AccessibleButton_kind_secondary');
|
||||
const isSpinnerRendered = (wrapper: RenderResult) => !!wrapper.container.querySelector('.mx_Spinner');
|
||||
const getMessage = (wrapper: RenderResult) =>
|
||||
wrapper.container.querySelector<HTMLDivElement>('.mx_RoomPreviewBar_message');
|
||||
const getActions = (wrapper: RenderResult) =>
|
||||
wrapper.container.querySelector<HTMLDivElement>('.mx_RoomPreviewBar_actions');
|
||||
const getPrimaryActionButton = (wrapper: RenderResult) =>
|
||||
getActions(wrapper).querySelector('.mx_AccessibleButton_kind_primary');
|
||||
const getSecondaryActionButton = (wrapper: RenderResult) =>
|
||||
getActions(wrapper).querySelector('.mx_AccessibleButton_kind_secondary');
|
||||
|
||||
beforeEach(() => {
|
||||
stubClient();
|
||||
|
@ -128,6 +123,36 @@ describe('<RoomPreviewBar />', () => {
|
|||
expect(getMessage(component).textContent).toEqual('Join the conversation with an account');
|
||||
});
|
||||
|
||||
it("should send room oob data to start login", async () => {
|
||||
MatrixClientPeg.get().isGuest = jest.fn().mockReturnValue(true);
|
||||
const component = getComponent({
|
||||
oobData: {
|
||||
name: "Room Name",
|
||||
avatarUrl: "mxc://foo/bar",
|
||||
inviterName: "Charlie",
|
||||
},
|
||||
});
|
||||
|
||||
const dispatcherSpy = jest.fn();
|
||||
const dispatcherRef = defaultDispatcher.register(dispatcherSpy);
|
||||
|
||||
expect(getMessage(component).textContent).toEqual('Join the conversation with an account');
|
||||
fireEvent.click(getPrimaryActionButton(component));
|
||||
|
||||
await waitFor(() => expect(dispatcherSpy).toHaveBeenCalledWith(expect.objectContaining({
|
||||
screenAfterLogin: {
|
||||
screen: 'room',
|
||||
params: expect.objectContaining({
|
||||
room_name: "Room Name",
|
||||
room_avatar_url: "mxc://foo/bar",
|
||||
inviter_name: "Charlie",
|
||||
}),
|
||||
},
|
||||
})));
|
||||
|
||||
defaultDispatcher.unregister(dispatcherRef);
|
||||
});
|
||||
|
||||
it('renders kicked message', () => {
|
||||
const room = createRoom(roomId, otherUserId);
|
||||
jest.spyOn(room, 'getMember').mockReturnValue(makeMockRoomMember({ isKicked: true }));
|
||||
|
@ -233,18 +258,14 @@ describe('<RoomPreviewBar />', () => {
|
|||
|
||||
it('joins room on primary button click', () => {
|
||||
const component = getComponent({ inviterName, room, onJoinClick, onRejectClick });
|
||||
act(() => {
|
||||
Simulate.click(getPrimaryActionButton(component));
|
||||
});
|
||||
fireEvent.click(getPrimaryActionButton(component));
|
||||
|
||||
expect(onJoinClick).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('rejects invite on secondary button click', () => {
|
||||
const component = getComponent({ inviterName, room, onJoinClick, onRejectClick });
|
||||
act(() => {
|
||||
Simulate.click(getSecondaryActionButton(component));
|
||||
});
|
||||
fireEvent.click(getSecondaryActionButton(component));
|
||||
|
||||
expect(onRejectClick).toHaveBeenCalled();
|
||||
});
|
||||
|
@ -296,9 +317,7 @@ describe('<RoomPreviewBar />', () => {
|
|||
await new Promise(setImmediate);
|
||||
expect(getPrimaryActionButton(component)).toBeTruthy();
|
||||
expect(getSecondaryActionButton(component)).toBeFalsy();
|
||||
act(() => {
|
||||
Simulate.click(getPrimaryActionButton(component));
|
||||
});
|
||||
fireEvent.click(getPrimaryActionButton(component));
|
||||
expect(onJoinClick).toHaveBeenCalled();
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue