diff --git a/test/components/views/messages/TextualBody-test.tsx b/test/components/views/messages/TextualBody-test.tsx
index 01e969a031..5c98cb6eab 100644
--- a/test/components/views/messages/TextualBody-test.tsx
+++ b/test/components/views/messages/TextualBody-test.tsx
@@ -15,10 +15,9 @@ limitations under the License.
 */
 
 import React from "react";
-// eslint-disable-next-line deprecate/import
-import { mount } from "enzyme";
 import { MatrixClient } from "matrix-js-sdk/src/matrix";
 import { MockedObject } from "jest-mock";
+import { render } from "@testing-library/react";
 
 import { getMockClientWithEventEmitter, mkEvent, mkStubRoom } from "../../../test-utils";
 import { MatrixClientPeg } from "../../../../src/MatrixClientPeg";
@@ -64,11 +63,12 @@ describe("<TextualBody />", () => {
         permalinkCreator: new RoomPermalinkCreator(defaultRoom),
         mediaEventHelper: {} as MediaEventHelper,
     };
-    const getComponent = (props = {}, matrixClient: MatrixClient = defaultMatrixClient) =>
-        mount(<TextualBody {...defaultProps} {...props} />, {
-            wrappingComponent: MatrixClientContext.Provider,
-            wrappingComponentProps: { value: matrixClient },
-        });
+    const getComponent = (props = {}, matrixClient: MatrixClient = defaultMatrixClient, renderingFn?: any) =>
+        (renderingFn ?? render)(
+            <MatrixClientContext.Provider value={matrixClient}>
+                <TextualBody {...defaultProps} {...props} />
+            </MatrixClientContext.Provider>,
+        );
 
     it("renders m.emote correctly", () => {
         DMRoomMap.makeShared();
@@ -84,10 +84,10 @@ describe("<TextualBody />", () => {
             event: true,
         });
 
-        const wrapper = getComponent({ mxEvent: ev });
-        expect(wrapper.text()).toBe("* sender winks");
-        const content = wrapper.find(".mx_EventTile_body");
-        expect(content.html()).toBe('<span class="mx_EventTile_body" dir="auto">winks</span>');
+        const { container } = getComponent({ mxEvent: ev });
+        expect(container).toHaveTextContent("* sender winks");
+        const content = container.querySelector(".mx_EventTile_body");
+        expect(content).toContainHTML('<span class="mx_EventTile_body" dir="auto">winks</span>');
     });
 
     it("renders m.notice correctly", () => {
@@ -104,10 +104,10 @@ describe("<TextualBody />", () => {
             event: true,
         });
 
-        const wrapper = getComponent({ mxEvent: ev });
-        expect(wrapper.text()).toBe(ev.getContent().body);
-        const content = wrapper.find(".mx_EventTile_body");
-        expect(content.html()).toBe(`<span class="mx_EventTile_body" dir="auto">${ev.getContent().body}</span>`);
+        const { container } = getComponent({ mxEvent: ev });
+        expect(container).toHaveTextContent(ev.getContent().body);
+        const content = container.querySelector(".mx_EventTile_body");
+        expect(content).toContainHTML(`<span class="mx_EventTile_body" dir="auto">${ev.getContent().body}</span>`);
     });
 
     describe("renders plain-text m.text correctly", () => {
@@ -127,10 +127,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev });
-            expect(wrapper.text()).toBe(ev.getContent().body);
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toBe(`<span class="mx_EventTile_body" dir="auto">${ev.getContent().body}</span>`);
+            const { container } = getComponent({ mxEvent: ev });
+            expect(container).toHaveTextContent(ev.getContent().body);
+            const content = container.querySelector(".mx_EventTile_body");
+            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
@@ -146,10 +146,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev });
-            expect(wrapper.text()).toBe(ev.getContent().body);
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toBe(
+            const { container } = getComponent({ mxEvent: ev });
+            expect(container).toHaveTextContent(ev.getContent().body);
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toContainHTML(
                 '<span class="mx_EventTile_body" dir="auto">' +
                     'Visit <a href="https://matrix.org/" class="linkified" target="_blank" rel="noreferrer noopener">' +
                     "https://matrix.org/</a></span>",
@@ -187,10 +187,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev }, matrixClient);
-            expect(wrapper.text()).toBe("foo baz bar del u");
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toBe(
+            const { container } = getComponent({ mxEvent: ev }, matrixClient);
+            expect(container).toHaveTextContent("foo baz bar del u");
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toContainHTML(
                 '<span class="mx_EventTile_body markdown-body" dir="auto">' +
                     ev.getContent().formatted_body +
                     "</span>",
@@ -211,10 +211,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev }, matrixClient);
-            expect(wrapper.text()).toBe("Hey (movie) the movie was awesome");
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toBe(
+            const { container } = getComponent({ mxEvent: ev }, matrixClient);
+            expect(container).toHaveTextContent("Hey (movie) the movie was awesome");
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toContainHTML(
                 '<span class="mx_EventTile_body markdown-body" dir="auto">' +
                     "Hey <span>" +
                     '<span class="mx_EventTile_spoiler">' +
@@ -238,10 +238,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev }, matrixClient);
-            expect(wrapper.text()).toBe("Visit https://matrix.org/\n1https://matrix.org/\n\n");
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toMatchSnapshot();
+            const { container } = getComponent({ mxEvent: ev }, matrixClient);
+            expect(container).toHaveTextContent("Visit https://matrix.org/ 1https://matrix.org/");
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toMatchSnapshot();
         });
 
         // 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,
             });
 
-            const wrapper = getComponent({ mxEvent: ev }, matrixClient);
-            expect(wrapper.text()).toBe("Hey Member");
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toMatchSnapshot();
+            const { container } = getComponent({ mxEvent: ev }, matrixClient);
+            expect(container).toHaveTextContent("Hey Member");
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toMatchSnapshot();
         });
 
         it("pills do not appear in code blocks", () => {
@@ -279,10 +279,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev });
-            expect(wrapper.text()).toBe("@room\n1@room\n\n");
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toMatchSnapshot();
+            const { container } = getComponent({ mxEvent: ev });
+            expect(container).toHaveTextContent("@room 1@room");
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toMatchSnapshot();
         });
 
         it("pills do not appear for event permalinks", () => {
@@ -303,10 +303,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev }, matrixClient);
-            expect(wrapper.text()).toBe("An event link with text");
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toBe(
+            const { container } = getComponent({ mxEvent: ev }, matrixClient);
+            expect(container).toHaveTextContent("An event link with text");
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toContainHTML(
                 '<span class="mx_EventTile_body markdown-body" dir="auto">' +
                     'An <a href="https://matrix.to/#/!ZxbRYPQXDXKGmDnJNg:example.com/' +
                     '$16085560162aNpaH:example.com?via=example.com" ' +
@@ -332,10 +332,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev }, matrixClient);
-            expect(wrapper.text()).toBe("A room name with vias");
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toBe(
+            const { container } = getComponent({ mxEvent: ev }, matrixClient);
+            expect(container).toHaveTextContent("A room name with vias");
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toContainHTML(
                 '<span class="mx_EventTile_body markdown-body" dir="auto">' +
                     'A <span><bdi><a class="mx_Pill mx_RoomPill" ' +
                     'href="https://matrix.to/#/!ZxbRYPQXDXKGmDnJNg:example.com' +
@@ -361,10 +361,10 @@ describe("<TextualBody />", () => {
                 event: true,
             });
 
-            const wrapper = getComponent({ mxEvent: ev }, matrixClient);
+            const { container } = getComponent({ mxEvent: ev }, matrixClient);
 
-            const content = wrapper.find(".mx_EventTile_body");
-            expect(content.html()).toBe(
+            const content = container.querySelector(".mx_EventTile_body");
+            expect(content).toContainHTML(
                 '<span class="mx_EventTile_body" dir="auto">' + "escaped *markdown*" + "</span>",
             );
         });
@@ -393,12 +393,13 @@ describe("<TextualBody />", () => {
             event: true,
         });
 
-        const wrapper = getComponent({ mxEvent: ev, showUrlPreview: true, onHeightChanged: jest.fn() }, matrixClient);
-        expect(wrapper.text()).toBe(ev.getContent().body);
+        const { container, rerender } = getComponent(
+            { mxEvent: ev, showUrlPreview: true, onHeightChanged: jest.fn() },
+            matrixClient,
+        );
 
-        let widgets = wrapper.find("LinkPreviewGroup");
-        // at this point we should have exactly one link
-        expect(widgets.at(0).prop("links")).toEqual(["https://matrix.org/"]);
+        expect(container).toHaveTextContent(ev.getContent().body);
+        expect(container.querySelector("a")).toHaveAttribute("href", "https://matrix.org/");
 
         // simulate an event edit and check the transition from the old URL preview to the new one
         const ev2 = mkEvent({
@@ -416,21 +417,18 @@ describe("<TextualBody />", () => {
         jest.spyOn(ev, "replacingEventDate").mockReturnValue(new Date(1993, 7, 3));
         ev.makeReplaced(ev2);
 
-        wrapper.setProps(
-            {
-                mxEvent: ev,
-                replacingEventId: ev.getId(),
-            },
-            () => {
-                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/"]);
-                });
-            },
+        getComponent(
+            { mxEvent: ev, showUrlPreview: true, onHeightChanged: jest.fn(), replacingEventId: ev.getId() },
+            matrixClient,
+            rerender,
         );
+
+        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]);
+        });
     });
 });
diff --git a/test/components/views/messages/__snapshots__/TextualBody-test.tsx.snap b/test/components/views/messages/__snapshots__/TextualBody-test.tsx.snap
index d2af91e1cf..02566d89f9 100644
--- a/test/components/views/messages/__snapshots__/TextualBody-test.tsx.snap
+++ b/test/components/views/messages/__snapshots__/TextualBody-test.tsx.snap
@@ -1,17 +1,112 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 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>
-<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></span></pre><span class="mx_EventTile_button mx_EventTile_copyButton "></span></div>
-</span>"
+<span
+  class="mx_EventTile_body markdown-body"
+  dir="auto"
+>
+  <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`] = `
-"<span class="mx_EventTile_body markdown-body" dir="auto"><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></span></pre><span class="mx_EventTile_button mx_EventTile_copyButton "></span></div>
-</span>"
+<span
+  class="mx_EventTile_body markdown-body"
+  dir="auto"
+>
+  <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>
+`;