Migrate TextualBody to RTL (#9845)

t3chguy/dedup-icons-17oct
Germain 2022-12-29 16:21:00 +00:00 committed by GitHub
parent 1e8b59ea40
commit adab82edae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 176 additions and 83 deletions

View File

@ -15,10 +15,9 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
// eslint-disable-next-line deprecate/import
import { mount } from "enzyme";
import { MatrixClient } from "matrix-js-sdk/src/matrix"; import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { MockedObject } from "jest-mock"; import { MockedObject } from "jest-mock";
import { render } from "@testing-library/react";
import { getMockClientWithEventEmitter, mkEvent, mkStubRoom } from "../../../test-utils"; import { getMockClientWithEventEmitter, mkEvent, mkStubRoom } from "../../../test-utils";
import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
@ -64,11 +63,12 @@ describe("<TextualBody />", () => {
permalinkCreator: new RoomPermalinkCreator(defaultRoom), permalinkCreator: new RoomPermalinkCreator(defaultRoom),
mediaEventHelper: {} as MediaEventHelper, mediaEventHelper: {} as MediaEventHelper,
}; };
const getComponent = (props = {}, matrixClient: MatrixClient = defaultMatrixClient) => const getComponent = (props = {}, matrixClient: MatrixClient = defaultMatrixClient, renderingFn?: any) =>
mount(<TextualBody {...defaultProps} {...props} />, { (renderingFn ?? render)(
wrappingComponent: MatrixClientContext.Provider, <MatrixClientContext.Provider value={matrixClient}>
wrappingComponentProps: { value: matrixClient }, <TextualBody {...defaultProps} {...props} />
}); </MatrixClientContext.Provider>,
);
it("renders m.emote correctly", () => { it("renders m.emote correctly", () => {
DMRoomMap.makeShared(); DMRoomMap.makeShared();
@ -84,10 +84,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }); const { container } = getComponent({ mxEvent: ev });
expect(wrapper.text()).toBe("* sender winks"); expect(container).toHaveTextContent("* sender winks");
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe('<span class="mx_EventTile_body" dir="auto">winks</span>'); expect(content).toContainHTML('<span class="mx_EventTile_body" dir="auto">winks</span>');
}); });
it("renders m.notice correctly", () => { it("renders m.notice correctly", () => {
@ -104,10 +104,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }); const { container } = getComponent({ mxEvent: ev });
expect(wrapper.text()).toBe(ev.getContent().body); expect(container).toHaveTextContent(ev.getContent().body);
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe(`<span class="mx_EventTile_body" dir="auto">${ev.getContent().body}</span>`); expect(content).toContainHTML(`<span class="mx_EventTile_body" dir="auto">${ev.getContent().body}</span>`);
}); });
describe("renders plain-text m.text correctly", () => { describe("renders plain-text m.text correctly", () => {
@ -127,10 +127,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }); const { container } = getComponent({ mxEvent: ev });
expect(wrapper.text()).toBe(ev.getContent().body); expect(container).toHaveTextContent(ev.getContent().body);
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe(`<span class="mx_EventTile_body" dir="auto">${ev.getContent().body}</span>`); expect(content).toContainHTML(`<span class="mx_EventTile_body" dir="auto">${ev.getContent().body}</span>`);
}); });
// If pills were rendered within a Portal/same shadow DOM then it'd be easier to test // If pills were rendered within a Portal/same shadow DOM then it'd be easier to test
@ -146,10 +146,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }); const { container } = getComponent({ mxEvent: ev });
expect(wrapper.text()).toBe(ev.getContent().body); expect(container).toHaveTextContent(ev.getContent().body);
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe( expect(content).toContainHTML(
'<span class="mx_EventTile_body" dir="auto">' + '<span class="mx_EventTile_body" dir="auto">' +
'Visit <a href="https://matrix.org/" class="linkified" target="_blank" rel="noreferrer noopener">' + 'Visit <a href="https://matrix.org/" class="linkified" target="_blank" rel="noreferrer noopener">' +
"https://matrix.org/</a></span>", "https://matrix.org/</a></span>",
@ -187,10 +187,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }, matrixClient); const { container } = getComponent({ mxEvent: ev }, matrixClient);
expect(wrapper.text()).toBe("foo baz bar del u"); expect(container).toHaveTextContent("foo baz bar del u");
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe( expect(content).toContainHTML(
'<span class="mx_EventTile_body markdown-body" dir="auto">' + '<span class="mx_EventTile_body markdown-body" dir="auto">' +
ev.getContent().formatted_body + ev.getContent().formatted_body +
"</span>", "</span>",
@ -211,10 +211,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }, matrixClient); const { container } = getComponent({ mxEvent: ev }, matrixClient);
expect(wrapper.text()).toBe("Hey (movie) the movie was awesome"); expect(container).toHaveTextContent("Hey (movie) the movie was awesome");
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe( expect(content).toContainHTML(
'<span class="mx_EventTile_body markdown-body" dir="auto">' + '<span class="mx_EventTile_body markdown-body" dir="auto">' +
"Hey <span>" + "Hey <span>" +
'<span class="mx_EventTile_spoiler">' + '<span class="mx_EventTile_spoiler">' +
@ -238,10 +238,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }, matrixClient); const { container } = getComponent({ mxEvent: ev }, matrixClient);
expect(wrapper.text()).toBe("Visit https://matrix.org/\n1https://matrix.org/\n\n"); expect(container).toHaveTextContent("Visit https://matrix.org/ 1https://matrix.org/");
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toMatchSnapshot(); expect(content).toMatchSnapshot();
}); });
// If pills were rendered within a Portal/same shadow DOM then it'd be easier to test // If pills were rendered within a Portal/same shadow DOM then it'd be easier to test
@ -259,10 +259,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }, matrixClient); const { container } = getComponent({ mxEvent: ev }, matrixClient);
expect(wrapper.text()).toBe("Hey Member"); expect(container).toHaveTextContent("Hey Member");
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toMatchSnapshot(); expect(content).toMatchSnapshot();
}); });
it("pills do not appear in code blocks", () => { it("pills do not appear in code blocks", () => {
@ -279,10 +279,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }); const { container } = getComponent({ mxEvent: ev });
expect(wrapper.text()).toBe("@room\n1@room\n\n"); expect(container).toHaveTextContent("@room 1@room");
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toMatchSnapshot(); expect(content).toMatchSnapshot();
}); });
it("pills do not appear for event permalinks", () => { it("pills do not appear for event permalinks", () => {
@ -303,10 +303,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }, matrixClient); const { container } = getComponent({ mxEvent: ev }, matrixClient);
expect(wrapper.text()).toBe("An event link with text"); expect(container).toHaveTextContent("An event link with text");
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe( expect(content).toContainHTML(
'<span class="mx_EventTile_body markdown-body" dir="auto">' + '<span class="mx_EventTile_body markdown-body" dir="auto">' +
'An <a href="https://matrix.to/#/!ZxbRYPQXDXKGmDnJNg:example.com/' + 'An <a href="https://matrix.to/#/!ZxbRYPQXDXKGmDnJNg:example.com/' +
'$16085560162aNpaH:example.com?via=example.com" ' + '$16085560162aNpaH:example.com?via=example.com" ' +
@ -332,10 +332,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }, matrixClient); const { container } = getComponent({ mxEvent: ev }, matrixClient);
expect(wrapper.text()).toBe("A room name with vias"); expect(container).toHaveTextContent("A room name with vias");
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe( expect(content).toContainHTML(
'<span class="mx_EventTile_body markdown-body" dir="auto">' + '<span class="mx_EventTile_body markdown-body" dir="auto">' +
'A <span><bdi><a class="mx_Pill mx_RoomPill" ' + 'A <span><bdi><a class="mx_Pill mx_RoomPill" ' +
'href="https://matrix.to/#/!ZxbRYPQXDXKGmDnJNg:example.com' + 'href="https://matrix.to/#/!ZxbRYPQXDXKGmDnJNg:example.com' +
@ -361,10 +361,10 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev }, matrixClient); const { container } = getComponent({ mxEvent: ev }, matrixClient);
const content = wrapper.find(".mx_EventTile_body"); const content = container.querySelector(".mx_EventTile_body");
expect(content.html()).toBe( expect(content).toContainHTML(
'<span class="mx_EventTile_body" dir="auto">' + "escaped *markdown*" + "</span>", '<span class="mx_EventTile_body" dir="auto">' + "escaped *markdown*" + "</span>",
); );
}); });
@ -393,12 +393,13 @@ describe("<TextualBody />", () => {
event: true, event: true,
}); });
const wrapper = getComponent({ mxEvent: ev, showUrlPreview: true, onHeightChanged: jest.fn() }, matrixClient); const { container, rerender } = getComponent(
expect(wrapper.text()).toBe(ev.getContent().body); { mxEvent: ev, showUrlPreview: true, onHeightChanged: jest.fn() },
matrixClient,
);
let widgets = wrapper.find("LinkPreviewGroup"); expect(container).toHaveTextContent(ev.getContent().body);
// at this point we should have exactly one link expect(container.querySelector("a")).toHaveAttribute("href", "https://matrix.org/");
expect(widgets.at(0).prop("links")).toEqual(["https://matrix.org/"]);
// simulate an event edit and check the transition from the old URL preview to the new one // simulate an event edit and check the transition from the old URL preview to the new one
const ev2 = mkEvent({ const ev2 = mkEvent({
@ -416,21 +417,18 @@ describe("<TextualBody />", () => {
jest.spyOn(ev, "replacingEventDate").mockReturnValue(new Date(1993, 7, 3)); jest.spyOn(ev, "replacingEventDate").mockReturnValue(new Date(1993, 7, 3));
ev.makeReplaced(ev2); ev.makeReplaced(ev2);
wrapper.setProps( getComponent(
{ { mxEvent: ev, showUrlPreview: true, onHeightChanged: jest.fn(), replacingEventId: ev.getId() },
mxEvent: ev, matrixClient,
replacingEventId: ev.getId(), rerender,
},
() => {
expect(wrapper.text()).toBe(ev2.getContent()["m.new_content"].body + "(edited)");
// XXX: this is to give TextualBody enough time for state to settle
wrapper.setState({}, () => {
widgets = wrapper.find("LinkPreviewGroup");
// at this point we should have exactly two links (not the matrix.org one anymore)
expect(widgets.at(0).prop("links")).toEqual(["https://vector.im/", "https://riot.im/"]);
});
},
); );
expect(container).toHaveTextContent(ev2.getContent()["m.new_content"].body + "(edited)");
const links = ["https://vector.im/", "https://riot.im/"];
const anchorNodes = container.querySelectorAll("a");
Array.from(anchorNodes).forEach((node, index) => {
expect(node).toHaveAttribute("href", links[index]);
});
}); });
}); });

View File

@ -1,17 +1,112 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<TextualBody /> renders formatted m.text correctly linkification is not applied to code blocks 1`] = ` exports[`<TextualBody /> renders formatted m.text correctly linkification is not applied to code blocks 1`] = `
"<span class="mx_EventTile_body markdown-body" dir="auto"><p>Visit <code>https://matrix.org/</code></p> <span
<div class="mx_EventTile_pre_container"><pre class="mx_EventTile_collapsedCodeBlock"><span class="mx_EventTile_lineNumbers"><span>1</span></span><code>https://matrix.org/ class="mx_EventTile_body markdown-body"
</code><span></span></pre><span class="mx_EventTile_button mx_EventTile_copyButton "></span></div> dir="auto"
</span>" >
<p>
Visit
<code>
https://matrix.org/
</code>
</p>
<div
class="mx_EventTile_pre_container"
>
<pre
class="mx_EventTile_collapsedCodeBlock"
>
<span
class="mx_EventTile_lineNumbers"
>
<span>
1
</span>
</span>
<code>
https://matrix.org/
</code>
<span />
</pre>
<span
class="mx_EventTile_button mx_EventTile_copyButton "
/>
</div>
</span>
`; `;
exports[`<TextualBody /> renders formatted m.text correctly pills do not appear in code blocks 1`] = ` exports[`<TextualBody /> renders formatted m.text correctly pills do not appear in code blocks 1`] = `
"<span class="mx_EventTile_body markdown-body" dir="auto"><p><code>@room</code></p> <span
<div class="mx_EventTile_pre_container"><pre class="mx_EventTile_collapsedCodeBlock"><span class="mx_EventTile_lineNumbers"><span>1</span></span><code>@room class="mx_EventTile_body markdown-body"
</code><span></span></pre><span class="mx_EventTile_button mx_EventTile_copyButton "></span></div> dir="auto"
</span>" >
<p>
<code>
@room
</code>
</p>
<div
class="mx_EventTile_pre_container"
>
<pre
class="mx_EventTile_collapsedCodeBlock"
>
<span
class="mx_EventTile_lineNumbers"
>
<span>
1
</span>
</span>
<code>
@room
</code>
<span />
</pre>
<span
class="mx_EventTile_button mx_EventTile_copyButton "
/>
</div>
</span>
`; `;
exports[`<TextualBody /> renders formatted m.text correctly pills get injected correctly into the DOM 1`] = `"<span class="mx_EventTile_body markdown-body" dir="auto">Hey <span><bdi><a class="mx_Pill mx_UserPill"><img class="mx_BaseAvatar mx_BaseAvatar_image" src="mxc://avatar.url/image.png" style="width: 16px; height: 16px;" alt="" data-testid="avatar-img" aria-hidden="true"><span class="mx_Pill_linkText">Member</span></a></bdi></span></span>"`; exports[`<TextualBody /> renders formatted m.text correctly pills get injected correctly into the DOM 1`] = `
<span
class="mx_EventTile_body markdown-body"
dir="auto"
>
Hey
<span>
<bdi>
<a
class="mx_Pill mx_UserPill"
>
<img
alt=""
aria-hidden="true"
class="mx_BaseAvatar mx_BaseAvatar_image"
data-testid="avatar-img"
src="mxc://avatar.url/image.png"
style="width: 16px; height: 16px;"
/>
<span
class="mx_Pill_linkText"
>
Member
</span>
</a>
</bdi>
</span>
</span>
`;