diff --git a/src/components/views/messages/MImageBody.tsx b/src/components/views/messages/MImageBody.tsx index 84e4e763de..27ccdd4228 100644 --- a/src/components/views/messages/MImageBody.tsx +++ b/src/components/views/messages/MImageBody.tsx @@ -389,7 +389,7 @@ export default class MImageBody extends React.Component { thumbUrl: string | null, content: IMediaEventContent, forcedHeight?: number, - ): JSX.Element { + ): ReactNode { if (!thumbUrl) thumbUrl = contentUrl; // fallback // magic number @@ -524,16 +524,25 @@ export default class MImageBody extends React.Component { ); - return contentUrl ? this.wrapImage(contentUrl, thumbnail) : thumbnail; + return this.wrapImage(contentUrl, thumbnail); } // Overridden by MStickerBody - protected wrapImage(contentUrl: string, children: JSX.Element): JSX.Element { - return ( - - {children} - - ); + protected wrapImage(contentUrl: string | null | undefined, children: JSX.Element): ReactNode { + if (contentUrl) { + return ( + + {children} + + ); + } else if (!this.state.showImage) { + return ( +
+ {children} +
+ ); + } + return children; } // Overridden by MStickerBody diff --git a/test/components/views/messages/MImageBody-test.tsx b/test/components/views/messages/MImageBody-test.tsx index 6534828bd6..ca400f13ee 100644 --- a/test/components/views/messages/MImageBody-test.tsx +++ b/test/components/views/messages/MImageBody-test.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { render, screen } from "@testing-library/react"; +import { fireEvent, render, screen } from "@testing-library/react"; import { EventType, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import fetchMock from "fetch-mock-jest"; import encrypt from "matrix-encrypt-attachment"; @@ -31,6 +31,7 @@ import { mockClientMethodsUser, } from "../../../test-utils"; import { MediaEventHelper } from "../../../../src/utils/MediaEventHelper"; +import SettingsStore from "../../../../src/settings/SettingsStore"; jest.mock("matrix-encrypt-attachment", () => ({ decryptAttachment: jest.fn(), @@ -61,6 +62,7 @@ describe("", () => { sender: userId, type: EventType.RoomMessage, content: { + body: "alt for a test image", info: { w: 40, h: 50, @@ -70,12 +72,18 @@ describe("", () => { }, }, }); + const props = { onHeightChanged: jest.fn(), onMessageAllowed: jest.fn(), permalinkCreator: new RoomPermalinkCreator(new Room(encryptedMediaEvent.getRoomId()!, cli, cli.getUserId()!)), }; + beforeEach(() => { + jest.spyOn(SettingsStore, "getValue").mockRestore(); + fetchMock.mockReset(); + }); + it("should show a thumbnail while image is being downloaded", async () => { fetchMock.getOnce(url, { status: 200 }); @@ -102,6 +110,8 @@ describe("", () => { />, ); + expect(fetchMock).toHaveBeenCalledWith(url); + await screen.findByText("Error downloading image"); }); @@ -119,4 +129,46 @@ describe("", () => { await screen.findByText("Error decrypting image"); }); + + describe("with image previews/thumbnails disabled", () => { + beforeEach(() => { + jest.spyOn(SettingsStore, "getValue").mockReturnValue(false); + }); + + it("should not download image", async () => { + fetchMock.getOnce(url, { status: 200 }); + + render( + , + ); + + expect(fetchMock).not.toHaveFetched(url); + }); + + it("should render hidden image placeholder", async () => { + fetchMock.getOnce(url, { status: 200 }); + + render( + , + ); + + expect(screen.getByText("Show image")).toBeInTheDocument(); + + fireEvent.click(screen.getByRole("button")); + + // image fetched after clicking show image + expect(fetchMock).toHaveFetched(url); + + // spinner while downloading image + expect(screen.getByRole("progressbar")).toBeInTheDocument(); + }); + }); });