diff --git a/src/components/views/rooms/wysiwyg_composer/components/LinkModal.tsx b/src/components/views/rooms/wysiwyg_composer/components/LinkModal.tsx
index 88230cd00df..d38a240d5c9 100644
--- a/src/components/views/rooms/wysiwyg_composer/components/LinkModal.tsx
+++ b/src/components/views/rooms/wysiwyg_composer/components/LinkModal.tsx
@@ -44,7 +44,7 @@ interface LinkModalProps {
onClose: () => void;
}
-function LinkModal({ composer, isTextEnabled, onClose }: LinkModalProps) {
+export function LinkModal({ composer, isTextEnabled, onClose }: LinkModalProps) {
const composerContext = useComposerContext();
const [fields, setFields] = useState({ text: "", link: "" });
diff --git a/test/components/views/rooms/wysiwyg_composer/components/FormattingButtons-test.tsx b/test/components/views/rooms/wysiwyg_composer/components/FormattingButtons-test.tsx
index d143e43a628..a467aa404e7 100644
--- a/test/components/views/rooms/wysiwyg_composer/components/FormattingButtons-test.tsx
+++ b/test/components/views/rooms/wysiwyg_composer/components/FormattingButtons-test.tsx
@@ -20,6 +20,7 @@ import userEvent from "@testing-library/user-event";
import { AllActionStates, FormattingFunctions } from "@matrix-org/matrix-wysiwyg";
import { FormattingButtons } from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/FormattingButtons";
+import * as LinkModal from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/LinkModal";
describe("FormattingButtons", () => {
const wysiwyg = {
@@ -28,6 +29,7 @@ describe("FormattingButtons", () => {
underline: jest.fn(),
strikeThrough: jest.fn(),
inlineCode: jest.fn(),
+ link: jest.fn(),
} as unknown as FormattingFunctions;
const actionStates = {
@@ -36,6 +38,7 @@ describe("FormattingButtons", () => {
underline: "enabled",
strikeThrough: "enabled",
inlineCode: "enabled",
+ link: "enabled",
} as AllActionStates;
afterEach(() => {
@@ -52,16 +55,19 @@ describe("FormattingButtons", () => {
expect(screen.getByLabelText("Underline")).not.toHaveClass("mx_FormattingButtons_active");
expect(screen.getByLabelText("Strikethrough")).not.toHaveClass("mx_FormattingButtons_active");
expect(screen.getByLabelText("Code")).not.toHaveClass("mx_FormattingButtons_active");
+ expect(screen.getByLabelText("Link")).not.toHaveClass("mx_FormattingButtons_active");
});
it("Should call wysiwyg function on button click", () => {
// When
+ const spy = jest.spyOn(LinkModal, "openLinkModal");
render();
screen.getByLabelText("Bold").click();
screen.getByLabelText("Italic").click();
screen.getByLabelText("Underline").click();
screen.getByLabelText("Strikethrough").click();
screen.getByLabelText("Code").click();
+ screen.getByLabelText("Link").click();
// Then
expect(wysiwyg.bold).toHaveBeenCalledTimes(1);
@@ -69,6 +75,7 @@ describe("FormattingButtons", () => {
expect(wysiwyg.underline).toHaveBeenCalledTimes(1);
expect(wysiwyg.strikeThrough).toHaveBeenCalledTimes(1);
expect(wysiwyg.inlineCode).toHaveBeenCalledTimes(1);
+ expect(spy).toHaveBeenCalledTimes(1);
});
it("Should display the tooltip on mouse over", async () => {
diff --git a/test/components/views/rooms/wysiwyg_composer/components/LinkModal-test.tsx b/test/components/views/rooms/wysiwyg_composer/components/LinkModal-test.tsx
new file mode 100644
index 00000000000..c51961b24f9
--- /dev/null
+++ b/test/components/views/rooms/wysiwyg_composer/components/LinkModal-test.tsx
@@ -0,0 +1,124 @@
+/*
+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 { FormattingFunctions } from "@matrix-org/matrix-wysiwyg";
+import { render, screen, waitFor } from "@testing-library/react";
+import React from "react";
+import userEvent from "@testing-library/user-event";
+
+import { ComposerContext } from "../../../../../../src/components/views/rooms/wysiwyg_composer/ComposerContext";
+import { LinkModal } from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/LinkModal";
+import { mockPlatformPeg } from "../../../../../test-utils";
+import * as selection from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/selection";
+
+describe("LinkModal", () => {
+ const composer = {
+ link: jest.fn(),
+ } as unknown as FormattingFunctions;
+ const defaultValue = { focusNode: null, anchorNode: null, focusOffset: 3, anchorOffset: 4 };
+
+ const customRender = (isTextEnabled: boolean, onClose: () => void) => {
+ return render(
+
+
+ ,
+ );
+ };
+
+ mockPlatformPeg({ overrideBrowserShortcuts: jest.fn().mockReturnValue(false) });
+ const selectionSpy = jest.spyOn(selection, "setSelection");
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ jest.useRealTimers();
+ });
+
+ it("Should create a link", async () => {
+ // When
+ const onClose = jest.fn();
+ customRender(false, onClose);
+
+ // Then
+ expect(screen.getByLabelText("Link")).toBeTruthy();
+ expect(screen.getByText("Save")).toBeDisabled();
+
+ // When
+ await userEvent.type(screen.getByLabelText("Link"), "l");
+
+ // Then
+ await waitFor(() => {
+ expect(screen.getByText("Save")).toBeEnabled();
+ expect(screen.getByLabelText("Link")).toHaveAttribute("value", "l");
+ });
+
+ // When
+ jest.useFakeTimers();
+ screen.getByText("Save").click();
+
+ // Then
+ expect(selectionSpy).toHaveBeenCalledWith(defaultValue);
+ expect(onClose).toBeCalledTimes(1);
+
+ // When
+ jest.runAllTimers();
+
+ // Then
+ expect(composer.link).toHaveBeenCalledWith("l", undefined);
+ });
+
+ it("Should create a link with text", async () => {
+ // When
+ const onClose = jest.fn();
+ customRender(true, onClose);
+
+ // Then
+ expect(screen.getByLabelText("Text")).toBeTruthy();
+ expect(screen.getByLabelText("Link")).toBeTruthy();
+ expect(screen.getByText("Save")).toBeDisabled();
+
+ // When
+ await userEvent.type(screen.getByLabelText("Text"), "t");
+
+ // Then
+ await waitFor(() => {
+ expect(screen.getByText("Save")).toBeDisabled();
+ expect(screen.getByLabelText("Text")).toHaveAttribute("value", "t");
+ });
+
+ // When
+ await userEvent.type(screen.getByLabelText("Link"), "l");
+
+ // Then
+ await waitFor(() => {
+ expect(screen.getByText("Save")).toBeEnabled();
+ expect(screen.getByLabelText("Link")).toHaveAttribute("value", "l");
+ });
+
+ // When
+ jest.useFakeTimers();
+ screen.getByText("Save").click();
+
+ // Then
+ expect(selectionSpy).toHaveBeenCalledWith(defaultValue);
+ expect(onClose).toBeCalledTimes(1);
+
+ // When
+ jest.runAllTimers();
+
+ // Then
+ expect(composer.link).toHaveBeenCalledWith("l", "t");
+ });
+});