diff --git a/src/components/views/rooms/wysiwyg_composer/WysiwygComposer.tsx b/src/components/views/rooms/wysiwyg_composer/WysiwygComposer.tsx
index f1d63d9a62..0c416f06fa 100644
--- a/src/components/views/rooms/wysiwyg_composer/WysiwygComposer.tsx
+++ b/src/components/views/rooms/wysiwyg_composer/WysiwygComposer.tsx
@@ -26,7 +26,7 @@ import { useMatrixClientContext } from '../../../../contexts/MatrixClientContext
interface WysiwygProps {
disabled?: boolean;
onChange: (content: string) => void;
- relation: IEventRelation;
+ relation?: IEventRelation;
replyToEvent?: MatrixEvent;
permalinkCreator: RoomPermalinkCreator;
includeReplyLegacyFallback?: boolean;
@@ -54,7 +54,16 @@ export function WysiwygComposer(
return (
{ children?.(memoizedSendMessage) }
diff --git a/test/components/views/rooms/wysiwyg_composer/WysiwygComposer-test.tsx b/test/components/views/rooms/wysiwyg_composer/WysiwygComposer-test.tsx
new file mode 100644
index 0000000000..9745dc7f8c
--- /dev/null
+++ b/test/components/views/rooms/wysiwyg_composer/WysiwygComposer-test.tsx
@@ -0,0 +1,147 @@
+/*
+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 { act, render, screen } from "@testing-library/react";
+import "@testing-library/jest-dom";
+
+import { IRoomState } from "../../../../../src/components/structures/RoomView";
+import RoomContext, { TimelineRenderingType } from "../../../../../src/contexts/RoomContext";
+import { Layout } from "../../../../../src/settings/enums/Layout";
+import { createTestClient, mkEvent, mkStubRoom } from "../../../../test-utils";
+import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext";
+import { WysiwygComposer } from "../../../../../src/components/views/rooms/wysiwyg_composer/WysiwygComposer";
+
+let callOnChange: (content: string) => void;
+
+// The wysiwyg fetch wasm bytes and a specific workaround is needed to make it works in a node (jest) environnement
+// See https://github.com/matrix-org/matrix-wysiwyg/blob/main/platforms/web/test.setup.ts
+jest.mock("@matrix-org/matrix-wysiwyg", () => ({
+ useWysiwyg: ({ onChange }) => {
+ callOnChange = onChange;
+ return { ref: { current: null }, isWysiwygReady: true, wysiwyg: { clear: () => void 0 } };
+ },
+}));
+
+describe('WysiwygComposer', () => {
+ afterEach(() => {
+ jest.resetAllMocks();
+ });
+
+ const permalinkCreator = jest.fn() as any;
+ const mockClient = createTestClient();
+ const mockEvent = mkEvent({
+ type: "m.room.message",
+ room: 'myfakeroom',
+ user: 'myfakeuser',
+ content: { "msgtype": "m.text", "body": "Replying to this" },
+ event: true,
+ });
+ const mockRoom = mkStubRoom('myfakeroom', 'myfakeroom', mockClient) as any;
+ mockRoom.findEventById = jest.fn(eventId => {
+ return eventId === mockEvent.getId() ? mockEvent : null;
+ });
+
+ const defaultRoomContext: IRoomState = {
+ room: mockRoom,
+ roomLoading: true,
+ peekLoading: false,
+ shouldPeek: true,
+ membersLoaded: false,
+ numUnreadMessages: 0,
+ canPeek: false,
+ showApps: false,
+ isPeeking: false,
+ showRightPanel: true,
+ joining: false,
+ atEndOfLiveTimeline: true,
+ showTopUnreadMessagesBar: false,
+ statusBarVisible: false,
+ canReact: false,
+ canSendMessages: false,
+ canSendVoiceBroadcasts: 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,
+ canSelfRedact: false,
+ resizing: false,
+ narrow: false,
+ };
+
+ let sendMessage: () => void;
+ const customRender = (onChange = (content: string) => void 0, disabled = false) => {
+ return render(
+
+
+
+ { (_sendMessage) => {
+ sendMessage = _sendMessage;
+ } }
+
+ ,
+ );
+ };
+
+ it('Should have contentEditable at false when disabled', () => {
+ // When
+ customRender(null, true);
+
+ // Then
+ expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "false");
+ });
+
+ it('Should call onChange handler', (done) => {
+ const html = 'html';
+ customRender((content) => {
+ expect(content).toBe((html));
+ done();
+ });
+ act(() => callOnChange(html));
+ });
+
+ it('Should send message, call clear and focus the textbox', async () => {
+ // When
+ const html = 'html';
+ await new Promise((resolve) => {
+ customRender(() => resolve(null));
+ act(() => callOnChange(html));
+ });
+ act(() => sendMessage());
+
+ // Then
+ const expectedContent = {
+ "body": html,
+ "format": "org.matrix.custom.html",
+ "formatted_body": html,
+ "msgtype": "m.text",
+ };
+ expect(mockClient.sendMessage).toBeCalledWith('myfakeroom', null, expectedContent);
+ expect(screen.getByRole('textbox')).toHaveFocus();
+ });
+});
+
diff --git a/test/components/views/rooms/wysisyg_composer/message-test.ts b/test/components/views/rooms/wysiwyg_composer/message-test.ts
similarity index 100%
rename from test/components/views/rooms/wysisyg_composer/message-test.ts
rename to test/components/views/rooms/wysiwyg_composer/message-test.ts