Replace some enzyme tests by @testing-library/react (#9822)
* Replace MessageComposerButtons-test.tsx enzyme by @testing-library/react * Replace HtmlUtils-test.tsx enzyme by @testing-library/react
This commit is contained in:
parent
249bd779f2
commit
88c3864682
2 changed files with 74 additions and 140 deletions
|
@ -15,9 +15,8 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
// eslint-disable-next-line deprecate/import
|
|
||||||
import { mount } from "enzyme";
|
|
||||||
import { mocked } from "jest-mock";
|
import { mocked } from "jest-mock";
|
||||||
|
import { render, screen } from "@testing-library/react";
|
||||||
|
|
||||||
import { topicToHtml } from "../src/HtmlUtils";
|
import { topicToHtml } from "../src/HtmlUtils";
|
||||||
import SettingsStore from "../src/settings/SettingsStore";
|
import SettingsStore from "../src/settings/SettingsStore";
|
||||||
|
@ -31,38 +30,35 @@ const enableHtmlTopicFeature = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("HtmlUtils", () => {
|
describe("HtmlUtils", () => {
|
||||||
|
function getContent() {
|
||||||
|
return screen.getByRole("contentinfo").children[0].innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
it("converts plain text topic to HTML", () => {
|
it("converts plain text topic to HTML", () => {
|
||||||
const component = mount(<div>{topicToHtml("pizza", null, null, false)}</div>);
|
render(<div role="contentinfo">{topicToHtml("pizza", undefined, null, false)}</div>);
|
||||||
const wrapper = component.render();
|
expect(getContent()).toEqual("pizza");
|
||||||
expect(wrapper.children().first().html()).toEqual("pizza");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("converts plain text topic with emoji to HTML", () => {
|
it("converts plain text topic with emoji to HTML", () => {
|
||||||
const component = mount(<div>{topicToHtml("pizza 🍕", null, null, false)}</div>);
|
render(<div role="contentinfo">{topicToHtml("pizza 🍕", undefined, null, false)}</div>);
|
||||||
const wrapper = component.render();
|
expect(getContent()).toEqual('pizza <span class="mx_Emoji" title=":pizza:">🍕</span>');
|
||||||
expect(wrapper.children().first().html()).toEqual('pizza <span class="mx_Emoji" title=":pizza:">🍕</span>');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("converts literal HTML topic to HTML", async () => {
|
it("converts literal HTML topic to HTML", async () => {
|
||||||
enableHtmlTopicFeature();
|
enableHtmlTopicFeature();
|
||||||
const component = mount(<div>{topicToHtml("<b>pizza</b>", null, null, false)}</div>);
|
render(<div role="contentinfo">{topicToHtml("<b>pizza</b>", undefined, null, false)}</div>);
|
||||||
const wrapper = component.render();
|
expect(getContent()).toEqual("<b>pizza</b>");
|
||||||
expect(wrapper.children().first().html()).toEqual("<b>pizza</b>");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("converts true HTML topic to HTML", async () => {
|
it("converts true HTML topic to HTML", async () => {
|
||||||
enableHtmlTopicFeature();
|
enableHtmlTopicFeature();
|
||||||
const component = mount(<div>{topicToHtml("**pizza**", "<b>pizza</b>", null, false)}</div>);
|
render(<div role="contentinfo">{topicToHtml("**pizza**", "<b>pizza</b>", null, false)}</div>);
|
||||||
const wrapper = component.render();
|
expect(getContent()).toEqual("<b>pizza</b>");
|
||||||
expect(wrapper.children().first().html()).toEqual("<b>pizza</b>");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("converts true HTML topic with emoji to HTML", async () => {
|
it("converts true HTML topic with emoji to HTML", async () => {
|
||||||
enableHtmlTopicFeature();
|
enableHtmlTopicFeature();
|
||||||
const component = mount(<div>{topicToHtml("**pizza** 🍕", "<b>pizza</b> 🍕", null, false)}</div>);
|
render(<div role="contentinfo">{topicToHtml("**pizza** 🍕", "<b>pizza</b> 🍕", null, false)}</div>);
|
||||||
const wrapper = component.render();
|
expect(getContent()).toEqual('<b>pizza</b> <span class="mx_Emoji" title=":pizza:">🍕</span>');
|
||||||
expect(wrapper.children().first().html()).toEqual(
|
|
||||||
'<b>pizza</b> <span class="mx_Emoji" title=":pizza:">🍕</span>',
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,19 +15,16 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
// eslint-disable-next-line deprecate/import
|
import { render, screen } from "@testing-library/react";
|
||||||
import { mount, ReactWrapper } from "enzyme";
|
|
||||||
import { Room } from "matrix-js-sdk/src/models/room";
|
|
||||||
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
|
|
||||||
|
|
||||||
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
import MatrixClientContext from "../../../../src/contexts/MatrixClientContext";
|
||||||
import { Layout } from "../../../../src/settings/enums/Layout";
|
import RoomContext from "../../../../src/contexts/RoomContext";
|
||||||
import RoomContext, { TimelineRenderingType } from "../../../../src/contexts/RoomContext";
|
import { createTestClient, getRoomContext, mkStubRoom } from "../../../test-utils";
|
||||||
import { createTestClient } from "../../../test-utils";
|
|
||||||
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
import { IRoomState } from "../../../../src/components/structures/RoomView";
|
||||||
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
|
||||||
import MessageComposerButtons from "../../../../src/components/views/rooms/MessageComposerButtons";
|
import MessageComposerButtons from "../../../../src/components/views/rooms/MessageComposerButtons";
|
||||||
|
|
||||||
|
describe("MessageComposerButtons", () => {
|
||||||
// @ts-ignore - we're deliberately not implementing the whole interface here, but
|
// @ts-ignore - we're deliberately not implementing the whole interface here, but
|
||||||
// can't use Partial<> for types because it'll annoy TS more than it helps.
|
// can't use Partial<> for types because it'll annoy TS more than it helps.
|
||||||
const mockProps: React.ComponentProps<typeof MessageComposerButtons> = {
|
const mockProps: React.ComponentProps<typeof MessageComposerButtons> = {
|
||||||
|
@ -40,9 +37,38 @@ const mockProps: React.ComponentProps<typeof MessageComposerButtons> = {
|
||||||
toggleButtonMenu: () => {},
|
toggleButtonMenu: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("MessageComposerButtons", () => {
|
const mockClient = createTestClient();
|
||||||
|
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mockClient);
|
||||||
|
|
||||||
|
function getButtonLabels() {
|
||||||
|
const getLabels = (elements: HTMLElement[]): string[] =>
|
||||||
|
elements
|
||||||
|
.map((element) => element.getAttribute("aria-label"))
|
||||||
|
.filter((label): label is string => label !== null);
|
||||||
|
|
||||||
|
const mainLabels: Array<string | string[]> = getLabels(screen.queryAllByRole("button"));
|
||||||
|
const menuLabels = getLabels(screen.queryAllByRole("menuitem"));
|
||||||
|
|
||||||
|
if (menuLabels.length) {
|
||||||
|
mainLabels.push(getLabels(screen.queryAllByRole("menuitem")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainLabels;
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapAndRender(component: React.ReactElement, narrow: boolean) {
|
||||||
|
const mockRoom = mkStubRoom("myfakeroom", "myfakeroom", mockClient) as any;
|
||||||
|
const defaultRoomContext: IRoomState = getRoomContext(mockRoom, { narrow });
|
||||||
|
|
||||||
|
return render(
|
||||||
|
<MatrixClientContext.Provider value={mockClient}>
|
||||||
|
<RoomContext.Provider value={defaultRoomContext}>{component}</RoomContext.Provider>
|
||||||
|
</MatrixClientContext.Provider>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
it("Renders emoji and upload buttons in wide mode", () => {
|
it("Renders emoji and upload buttons in wide mode", () => {
|
||||||
const buttons = wrapAndRender(
|
wrapAndRender(
|
||||||
<MessageComposerButtons
|
<MessageComposerButtons
|
||||||
{...mockProps}
|
{...mockProps}
|
||||||
isMenuOpen={false}
|
isMenuOpen={false}
|
||||||
|
@ -53,11 +79,11 @@ describe("MessageComposerButtons", () => {
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(buttonLabels(buttons)).toEqual(["Emoji", "Attachment", "More options"]);
|
expect(getButtonLabels()).toEqual(["Emoji", "Attachment", "More options"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Renders other buttons in menu in wide mode", () => {
|
it("Renders other buttons in menu in wide mode", () => {
|
||||||
const buttons = wrapAndRender(
|
wrapAndRender(
|
||||||
<MessageComposerButtons
|
<MessageComposerButtons
|
||||||
{...mockProps}
|
{...mockProps}
|
||||||
isMenuOpen={true}
|
isMenuOpen={true}
|
||||||
|
@ -68,7 +94,7 @@ describe("MessageComposerButtons", () => {
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(buttonLabels(buttons)).toEqual([
|
expect(getButtonLabels()).toEqual([
|
||||||
"Emoji",
|
"Emoji",
|
||||||
"Attachment",
|
"Attachment",
|
||||||
"More options",
|
"More options",
|
||||||
|
@ -77,7 +103,7 @@ describe("MessageComposerButtons", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Renders only some buttons in narrow mode", () => {
|
it("Renders only some buttons in narrow mode", () => {
|
||||||
const buttons = wrapAndRender(
|
wrapAndRender(
|
||||||
<MessageComposerButtons
|
<MessageComposerButtons
|
||||||
{...mockProps}
|
{...mockProps}
|
||||||
isMenuOpen={false}
|
isMenuOpen={false}
|
||||||
|
@ -88,11 +114,11 @@ describe("MessageComposerButtons", () => {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(buttonLabels(buttons)).toEqual(["Emoji", "More options"]);
|
expect(getButtonLabels()).toEqual(["Emoji", "More options"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Renders other buttons in menu (except voice messages) in narrow mode", () => {
|
it("Renders other buttons in menu (except voice messages) in narrow mode", () => {
|
||||||
const buttons = wrapAndRender(
|
wrapAndRender(
|
||||||
<MessageComposerButtons
|
<MessageComposerButtons
|
||||||
{...mockProps}
|
{...mockProps}
|
||||||
isMenuOpen={true}
|
isMenuOpen={true}
|
||||||
|
@ -103,12 +129,12 @@ describe("MessageComposerButtons", () => {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(buttonLabels(buttons)).toEqual(["Emoji", "More options", ["Attachment", "Sticker", "Poll", "Location"]]);
|
expect(getButtonLabels()).toEqual(["Emoji", "More options", ["Attachment", "Sticker", "Poll", "Location"]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("polls button", () => {
|
describe("polls button", () => {
|
||||||
it("should render when asked to", () => {
|
it("should render when asked to", () => {
|
||||||
const buttons = wrapAndRender(
|
wrapAndRender(
|
||||||
<MessageComposerButtons
|
<MessageComposerButtons
|
||||||
{...mockProps}
|
{...mockProps}
|
||||||
isMenuOpen={true}
|
isMenuOpen={true}
|
||||||
|
@ -119,15 +145,11 @@ describe("MessageComposerButtons", () => {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(buttonLabels(buttons)).toEqual([
|
expect(getButtonLabels()).toEqual(["Emoji", "More options", ["Attachment", "Sticker", "Poll", "Location"]]);
|
||||||
"Emoji",
|
|
||||||
"More options",
|
|
||||||
["Attachment", "Sticker", "Poll", "Location"],
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not render when asked not to", () => {
|
it("should not render when asked not to", () => {
|
||||||
const buttons = wrapAndRender(
|
wrapAndRender(
|
||||||
<MessageComposerButtons
|
<MessageComposerButtons
|
||||||
{...mockProps}
|
{...mockProps}
|
||||||
isMenuOpen={true}
|
isMenuOpen={true}
|
||||||
|
@ -138,7 +160,7 @@ describe("MessageComposerButtons", () => {
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(buttonLabels(buttons)).toEqual([
|
expect(getButtonLabels()).toEqual([
|
||||||
"Emoji",
|
"Emoji",
|
||||||
"More options",
|
"More options",
|
||||||
[
|
[
|
||||||
|
@ -153,7 +175,7 @@ describe("MessageComposerButtons", () => {
|
||||||
|
|
||||||
describe("with showVoiceBroadcastButton = true", () => {
|
describe("with showVoiceBroadcastButton = true", () => {
|
||||||
it("should render the »Voice broadcast« button", () => {
|
it("should render the »Voice broadcast« button", () => {
|
||||||
const buttons = wrapAndRender(
|
wrapAndRender(
|
||||||
<MessageComposerButtons
|
<MessageComposerButtons
|
||||||
{...mockProps}
|
{...mockProps}
|
||||||
isMenuOpen={true}
|
isMenuOpen={true}
|
||||||
|
@ -165,7 +187,7 @@ describe("MessageComposerButtons", () => {
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(buttonLabels(buttons)).toEqual([
|
expect(getButtonLabels()).toEqual([
|
||||||
"Emoji",
|
"Emoji",
|
||||||
"Attachment",
|
"Attachment",
|
||||||
"More options",
|
"More options",
|
||||||
|
@ -174,87 +196,3 @@ describe("MessageComposerButtons", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function wrapAndRender(component: React.ReactElement, narrow: boolean): ReactWrapper {
|
|
||||||
const mockClient = createTestClient();
|
|
||||||
jest.spyOn(MatrixClientPeg, "get").mockReturnValue(mockClient);
|
|
||||||
const roomId = "myroomid";
|
|
||||||
const mockRoom: any = {
|
|
||||||
currentState: undefined,
|
|
||||||
roomId,
|
|
||||||
client: mockClient,
|
|
||||||
getMember: function (userId: string): RoomMember {
|
|
||||||
return new RoomMember(roomId, userId);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const roomState = createRoomState(mockRoom, narrow);
|
|
||||||
|
|
||||||
return mount(
|
|
||||||
<MatrixClientContext.Provider value={mockClient}>
|
|
||||||
<RoomContext.Provider value={roomState}>{component}</RoomContext.Provider>
|
|
||||||
</MatrixClientContext.Provider>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function createRoomState(room: Room, narrow: boolean): IRoomState {
|
|
||||||
return {
|
|
||||||
room: room,
|
|
||||||
roomId: room.roomId,
|
|
||||||
roomLoading: true,
|
|
||||||
peekLoading: false,
|
|
||||||
shouldPeek: true,
|
|
||||||
membersLoaded: false,
|
|
||||||
numUnreadMessages: 0,
|
|
||||||
canSelfRedact: false,
|
|
||||||
canPeek: false,
|
|
||||||
showApps: false,
|
|
||||||
isPeeking: false,
|
|
||||||
showRightPanel: true,
|
|
||||||
joining: false,
|
|
||||||
atEndOfLiveTimeline: true,
|
|
||||||
showTopUnreadMessagesBar: false,
|
|
||||||
statusBarVisible: false,
|
|
||||||
canReact: false,
|
|
||||||
canSendMessages: false,
|
|
||||||
layout: Layout.Group,
|
|
||||||
lowBandwidth: false,
|
|
||||||
alwaysShowTimestamps: false,
|
|
||||||
showTwelveHourTimestamps: false,
|
|
||||||
readMarkerInViewThresholdMs: 3000,
|
|
||||||
readMarkerOutOfViewThresholdMs: 30000,
|
|
||||||
showHiddenEvents: false,
|
|
||||||
showReadReceipts: true,
|
|
||||||
showRedactions: true,
|
|
||||||
showJoinLeaves: true,
|
|
||||||
showAvatarChanges: true,
|
|
||||||
showDisplaynameChanges: true,
|
|
||||||
matrixClientIsReady: false,
|
|
||||||
timelineRenderingType: TimelineRenderingType.Room,
|
|
||||||
liveTimeline: undefined,
|
|
||||||
resizing: false,
|
|
||||||
narrow,
|
|
||||||
activeCall: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function buttonLabels(buttons: ReactWrapper): any[] {
|
|
||||||
// Note: Depends on the fact that the mini buttons use aria-label
|
|
||||||
// and the labels under More options use textContent
|
|
||||||
const mainButtons = buttons
|
|
||||||
.find("div.mx_MessageComposer_button[aria-label]")
|
|
||||||
.map((button: ReactWrapper) => button.prop("aria-label") as string)
|
|
||||||
.filter((x) => x);
|
|
||||||
|
|
||||||
const extraButtons = buttons
|
|
||||||
.find('.mx_MessageComposer_Menu div.mx_AccessibleButton[role="menuitem"]')
|
|
||||||
.map((button: ReactWrapper) => button.text())
|
|
||||||
.filter((x) => x);
|
|
||||||
|
|
||||||
const list: any[] = [...mainButtons];
|
|
||||||
|
|
||||||
if (extraButtons.length > 0) {
|
|
||||||
list.push(extraButtons);
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue