Apply prettier formatting
This commit is contained in:
parent
1cac306093
commit
526645c791
1576 changed files with 65385 additions and 62478 deletions
|
@ -24,11 +24,10 @@ import defaultDispatcher from "../../../../../src/dispatcher/dispatcher";
|
|||
import { Action } from "../../../../../src/dispatcher/actions";
|
||||
import { IRoomState } from "../../../../../src/components/structures/RoomView";
|
||||
import { createTestClient, flushPromises, getRoomContext, mkEvent, mkStubRoom } from "../../../../test-utils";
|
||||
import { EditWysiwygComposer }
|
||||
from "../../../../../src/components/views/rooms/wysiwyg_composer";
|
||||
import { EditWysiwygComposer } from "../../../../../src/components/views/rooms/wysiwyg_composer";
|
||||
import EditorStateTransfer from "../../../../../src/utils/EditorStateTransfer";
|
||||
|
||||
describe('EditWysiwygComposer', () => {
|
||||
describe("EditWysiwygComposer", () => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
@ -36,18 +35,18 @@ describe('EditWysiwygComposer', () => {
|
|||
const mockClient = createTestClient();
|
||||
const mockEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "Replying to this",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": 'Replying <b>to</b> this new content',
|
||||
msgtype: "m.text",
|
||||
body: "Replying to this",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: "Replying <b>to</b> this new content",
|
||||
},
|
||||
event: true,
|
||||
});
|
||||
const mockRoom = mkStubRoom('myfakeroom', 'myfakeroom', mockClient) as any;
|
||||
mockRoom.findEventById = jest.fn(eventId => {
|
||||
const mockRoom = mkStubRoom("myfakeroom", "myfakeroom", mockClient) as any;
|
||||
mockRoom.findEventById = jest.fn((eventId) => {
|
||||
return eventId === mockEvent.getId() ? mockEvent : null;
|
||||
});
|
||||
|
||||
|
@ -65,48 +64,48 @@ describe('EditWysiwygComposer', () => {
|
|||
);
|
||||
};
|
||||
|
||||
describe('Initialize with content', () => {
|
||||
it('Should initialize useWysiwyg with html content', async () => {
|
||||
describe("Initialize with content", () => {
|
||||
it("Should initialize useWysiwyg with html content", async () => {
|
||||
// When
|
||||
customRender(false, editorStateTransfer);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
|
||||
// Then
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('textbox')).toContainHTML(mockEvent.getContent()['formatted_body']));
|
||||
expect(screen.getByRole("textbox")).toContainHTML(mockEvent.getContent()["formatted_body"]),
|
||||
);
|
||||
});
|
||||
|
||||
it('Should initialize useWysiwyg with plain text content', async () => {
|
||||
it("Should initialize useWysiwyg with plain text content", async () => {
|
||||
// When
|
||||
const mockEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "Replying to this",
|
||||
msgtype: "m.text",
|
||||
body: "Replying to this",
|
||||
},
|
||||
event: true,
|
||||
});
|
||||
const editorStateTransfer = new EditorStateTransfer(mockEvent);
|
||||
customRender(false, editorStateTransfer);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
|
||||
// Then
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('textbox')).toContainHTML(mockEvent.getContent()['body']));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toContainHTML(mockEvent.getContent()["body"]));
|
||||
});
|
||||
|
||||
it('Should ignore when formatted_body is not filled', async () => {
|
||||
it("Should ignore when formatted_body is not filled", async () => {
|
||||
// When
|
||||
const mockEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "Replying to this",
|
||||
"format": "org.matrix.custom.html",
|
||||
msgtype: "m.text",
|
||||
body: "Replying to this",
|
||||
format: "org.matrix.custom.html",
|
||||
},
|
||||
event: true,
|
||||
});
|
||||
|
@ -115,40 +114,40 @@ describe('EditWysiwygComposer', () => {
|
|||
customRender(false, editorStateTransfer);
|
||||
|
||||
// Then
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
});
|
||||
|
||||
it('Should strip <mx-reply> tag from initial content', async () => {
|
||||
it("Should strip <mx-reply> tag from initial content", async () => {
|
||||
// When
|
||||
const mockEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "Replying to this",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": '<mx-reply>Reply</mx-reply>My content',
|
||||
msgtype: "m.text",
|
||||
body: "Replying to this",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: "<mx-reply>Reply</mx-reply>My content",
|
||||
},
|
||||
event: true,
|
||||
});
|
||||
|
||||
const editorStateTransfer = new EditorStateTransfer(mockEvent);
|
||||
customRender(false, editorStateTransfer);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
|
||||
// Then
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('textbox')).not.toContainHTML("<mx-reply>Reply</mx-reply>");
|
||||
expect(screen.getByRole('textbox')).toContainHTML("My content");
|
||||
expect(screen.getByRole("textbox")).not.toContainHTML("<mx-reply>Reply</mx-reply>");
|
||||
expect(screen.getByRole("textbox")).toContainHTML("My content");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edit and save actions', () => {
|
||||
describe("Edit and save actions", () => {
|
||||
beforeEach(async () => {
|
||||
customRender();
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
});
|
||||
|
||||
const spyDispatcher = jest.spyOn(defaultDispatcher, "dispatch");
|
||||
|
@ -156,9 +155,9 @@ describe('EditWysiwygComposer', () => {
|
|||
spyDispatcher.mockRestore();
|
||||
});
|
||||
|
||||
it('Should cancel edit on cancel button click', async () => {
|
||||
it("Should cancel edit on cancel button click", async () => {
|
||||
// When
|
||||
screen.getByText('Cancel').click();
|
||||
screen.getByText("Cancel").click();
|
||||
|
||||
// Then
|
||||
expect(spyDispatcher).toBeCalledWith({
|
||||
|
@ -172,43 +171,43 @@ describe('EditWysiwygComposer', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('Should send message on save button click', async () => {
|
||||
it("Should send message on save button click", async () => {
|
||||
// When
|
||||
const spyDispatcher = jest.spyOn(defaultDispatcher, "dispatch");
|
||||
fireEvent.input(screen.getByRole('textbox'), {
|
||||
data: 'foo bar',
|
||||
inputType: 'insertText',
|
||||
fireEvent.input(screen.getByRole("textbox"), {
|
||||
data: "foo bar",
|
||||
inputType: "insertText",
|
||||
});
|
||||
await waitFor(() => expect(screen.getByText('Save')).not.toHaveAttribute('disabled'));
|
||||
await waitFor(() => expect(screen.getByText("Save")).not.toHaveAttribute("disabled"));
|
||||
|
||||
// Then
|
||||
screen.getByText('Save').click();
|
||||
screen.getByText("Save").click();
|
||||
const expectedContent = {
|
||||
"body": ` * foo bar`,
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": ` * foo bar`,
|
||||
"m.new_content": {
|
||||
"body": "foo bar",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": "foo bar",
|
||||
"msgtype": "m.text",
|
||||
body: "foo bar",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: "foo bar",
|
||||
msgtype: "m.text",
|
||||
},
|
||||
"m.relates_to": {
|
||||
"event_id": mockEvent.getId(),
|
||||
"rel_type": "m.replace",
|
||||
event_id: mockEvent.getId(),
|
||||
rel_type: "m.replace",
|
||||
},
|
||||
"msgtype": "m.text",
|
||||
};
|
||||
expect(mockClient.sendMessage).toBeCalledWith(mockEvent.getRoomId(), null, expectedContent);
|
||||
expect(spyDispatcher).toBeCalledWith({ action: 'message_sent' });
|
||||
expect(spyDispatcher).toBeCalledWith({ action: "message_sent" });
|
||||
});
|
||||
});
|
||||
|
||||
it('Should focus when receiving an Action.FocusEditMessageComposer action', async () => {
|
||||
it("Should focus when receiving an Action.FocusEditMessageComposer action", async () => {
|
||||
// Given we don't have focus
|
||||
customRender();
|
||||
screen.getByLabelText('Bold').focus();
|
||||
expect(screen.getByRole('textbox')).not.toHaveFocus();
|
||||
screen.getByLabelText("Bold").focus();
|
||||
expect(screen.getByRole("textbox")).not.toHaveFocus();
|
||||
|
||||
// When we send the right action
|
||||
defaultDispatcher.dispatch({
|
||||
|
@ -217,14 +216,14 @@ describe('EditWysiwygComposer', () => {
|
|||
});
|
||||
|
||||
// Then the component gets the focus
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveFocus());
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveFocus());
|
||||
});
|
||||
|
||||
it('Should not focus when disabled', async () => {
|
||||
it("Should not focus when disabled", async () => {
|
||||
// Given we don't have focus and we are disabled
|
||||
customRender(true);
|
||||
screen.getByLabelText('Bold').focus();
|
||||
expect(screen.getByRole('textbox')).not.toHaveFocus();
|
||||
screen.getByLabelText("Bold").focus();
|
||||
expect(screen.getByRole("textbox")).not.toHaveFocus();
|
||||
|
||||
// When we send an action that would cause us to get focus
|
||||
act(() => {
|
||||
|
@ -243,7 +242,6 @@ describe('EditWysiwygComposer', () => {
|
|||
await flushPromises();
|
||||
|
||||
// Then we don't get it because we are disabled
|
||||
expect(screen.getByRole('textbox')).not.toHaveFocus();
|
||||
expect(screen.getByRole("textbox")).not.toHaveFocus();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -30,12 +30,16 @@ import { ComposerInsertPayload, ComposerType } from "../../../../../src/dispatch
|
|||
import { setSelection } from "../../../../../src/components/views/rooms/wysiwyg_composer/utils/selection";
|
||||
|
||||
jest.mock("../../../../../src/components/views/rooms/EmojiButton", () => ({
|
||||
EmojiButton: ({ addEmoji }: {addEmoji: (emoji: string) => void}) => {
|
||||
return <button aria-label="Emoji" type="button" onClick={() => addEmoji('🦫')}>Emoji</button>;
|
||||
EmojiButton: ({ addEmoji }: { addEmoji: (emoji: string) => void }) => {
|
||||
return (
|
||||
<button aria-label="Emoji" type="button" onClick={() => addEmoji("🦫")}>
|
||||
Emoji
|
||||
</button>
|
||||
);
|
||||
},
|
||||
}));
|
||||
|
||||
describe('SendWysiwygComposer', () => {
|
||||
describe("SendWysiwygComposer", () => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
@ -43,13 +47,13 @@ describe('SendWysiwygComposer', () => {
|
|||
const mockClient = createTestClient();
|
||||
const mockEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
content: { "msgtype": "m.text", "body": "Replying to this" },
|
||||
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 => {
|
||||
const mockRoom = mkStubRoom("myfakeroom", "myfakeroom", mockClient) as any;
|
||||
mockRoom.findEventById = jest.fn((eventId) => {
|
||||
return eventId === mockEvent.getId() ? mockEvent : null;
|
||||
});
|
||||
|
||||
|
@ -79,46 +83,54 @@ describe('SendWysiwygComposer', () => {
|
|||
onSend = (): void => void 0,
|
||||
disabled = false,
|
||||
isRichTextEnabled = true,
|
||||
placeholder?: string) => {
|
||||
placeholder?: string,
|
||||
) => {
|
||||
return render(
|
||||
<MatrixClientContext.Provider value={mockClient}>
|
||||
<RoomContext.Provider value={defaultRoomContext}>
|
||||
<SendWysiwygComposer onChange={onChange} onSend={onSend} disabled={disabled} isRichTextEnabled={isRichTextEnabled} menuPosition={aboveLeftOf({ top: 0, bottom: 0, right: 0 })} placeholder={placeholder} />
|
||||
<SendWysiwygComposer
|
||||
onChange={onChange}
|
||||
onSend={onSend}
|
||||
disabled={disabled}
|
||||
isRichTextEnabled={isRichTextEnabled}
|
||||
menuPosition={aboveLeftOf({ top: 0, bottom: 0, right: 0 })}
|
||||
placeholder={placeholder}
|
||||
/>
|
||||
</RoomContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
};
|
||||
|
||||
it('Should render WysiwygComposer when isRichTextEnabled is at true', () => {
|
||||
it("Should render WysiwygComposer when isRichTextEnabled is at true", () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), false, true);
|
||||
|
||||
// Then
|
||||
expect(screen.getByTestId('WysiwygComposer')).toBeTruthy();
|
||||
expect(screen.getByTestId("WysiwygComposer")).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Should render PlainTextComposer when isRichTextEnabled is at false', () => {
|
||||
it("Should render PlainTextComposer when isRichTextEnabled is at false", () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), false, false);
|
||||
|
||||
// Then
|
||||
expect(screen.getByTestId('PlainTextComposer')).toBeTruthy();
|
||||
expect(screen.getByTestId("PlainTextComposer")).toBeTruthy();
|
||||
});
|
||||
|
||||
describe.each([
|
||||
{ isRichTextEnabled: true, emptyContent: '<br>' },
|
||||
{ isRichTextEnabled: false, emptyContent: '' },
|
||||
{ isRichTextEnabled: true, emptyContent: "<br>" },
|
||||
{ isRichTextEnabled: false, emptyContent: "" },
|
||||
])(
|
||||
'Should focus when receiving an Action.FocusSendMessageComposer action',
|
||||
"Should focus when receiving an Action.FocusSendMessageComposer action",
|
||||
({ isRichTextEnabled, emptyContent }) => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('Should focus when receiving an Action.FocusSendMessageComposer action', async () => {
|
||||
it("Should focus when receiving an Action.FocusSendMessageComposer action", async () => {
|
||||
// Given we don't have focus
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
|
||||
// When we send the right action
|
||||
defaultDispatcher.dispatch({
|
||||
|
@ -127,18 +139,18 @@ describe('SendWysiwygComposer', () => {
|
|||
});
|
||||
|
||||
// Then the component gets the focus
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveFocus());
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveFocus());
|
||||
});
|
||||
|
||||
it('Should focus and clear when receiving an Action.ClearAndFocusSendMessageComposer', async () => {
|
||||
it("Should focus and clear when receiving an Action.ClearAndFocusSendMessageComposer", async () => {
|
||||
// Given we don't have focus
|
||||
const onChange = jest.fn();
|
||||
customRender(onChange, jest.fn(), false, isRichTextEnabled);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
|
||||
fireEvent.input(screen.getByRole('textbox'), {
|
||||
data: 'foo bar',
|
||||
inputType: 'insertText',
|
||||
fireEvent.input(screen.getByRole("textbox"), {
|
||||
data: "foo bar",
|
||||
inputType: "insertText",
|
||||
});
|
||||
|
||||
// When we send the right action
|
||||
|
@ -149,15 +161,15 @@ describe('SendWysiwygComposer', () => {
|
|||
|
||||
// Then the component gets the focus
|
||||
await waitFor(() => {
|
||||
expect(screen.getByRole('textbox')).toHaveTextContent(/^$/);
|
||||
expect(screen.getByRole('textbox')).toHaveFocus();
|
||||
expect(screen.getByRole("textbox")).toHaveTextContent(/^$/);
|
||||
expect(screen.getByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
});
|
||||
|
||||
it('Should focus when receiving a reply_to_event action', async () => {
|
||||
it("Should focus when receiving a reply_to_event action", async () => {
|
||||
// Given we don't have focus
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
|
||||
// When we send the right action
|
||||
defaultDispatcher.dispatch({
|
||||
|
@ -166,13 +178,13 @@ describe('SendWysiwygComposer', () => {
|
|||
});
|
||||
|
||||
// Then the component gets the focus
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveFocus());
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveFocus());
|
||||
});
|
||||
|
||||
it('Should not focus when disabled', async () => {
|
||||
it("Should not focus when disabled", async () => {
|
||||
// Given we don't have focus and we are disabled
|
||||
customRender(jest.fn(), jest.fn(), true, isRichTextEnabled);
|
||||
expect(screen.getByRole('textbox')).not.toHaveFocus();
|
||||
expect(screen.getByRole("textbox")).not.toHaveFocus();
|
||||
|
||||
// When we send an action that would cause us to get focus
|
||||
defaultDispatcher.dispatch({
|
||||
|
@ -189,114 +201,114 @@ describe('SendWysiwygComposer', () => {
|
|||
await flushPromises();
|
||||
|
||||
// Then we don't get it because we are disabled
|
||||
expect(screen.getByRole('textbox')).not.toHaveFocus();
|
||||
expect(screen.getByRole("textbox")).not.toHaveFocus();
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
describe.each([
|
||||
{ isRichTextEnabled: true },
|
||||
{ isRichTextEnabled: false },
|
||||
])('Placeholder when %s',
|
||||
describe.each([{ isRichTextEnabled: true }, { isRichTextEnabled: false }])(
|
||||
"Placeholder when %s",
|
||||
({ isRichTextEnabled }) => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('Should not has placeholder', async () => {
|
||||
it("Should not has placeholder", async () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
|
||||
// Then
|
||||
expect(screen.getByRole('textbox')).not.toHaveClass("mx_WysiwygComposer_Editor_content_placeholder");
|
||||
expect(screen.getByRole("textbox")).not.toHaveClass("mx_WysiwygComposer_Editor_content_placeholder");
|
||||
});
|
||||
|
||||
it('Should has placeholder', async () => {
|
||||
it("Should has placeholder", async () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled, 'my placeholder');
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled, "my placeholder");
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
|
||||
// Then
|
||||
expect(screen.getByRole('textbox')).toHaveClass("mx_WysiwygComposer_Editor_content_placeholder");
|
||||
expect(screen.getByRole("textbox")).toHaveClass("mx_WysiwygComposer_Editor_content_placeholder");
|
||||
});
|
||||
|
||||
it('Should display or not placeholder when editor content change', async () => {
|
||||
it("Should display or not placeholder when editor content change", async () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled, 'my placeholder');
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
screen.getByRole('textbox').innerHTML = 'f';
|
||||
fireEvent.input(screen.getByRole('textbox'), {
|
||||
data: 'f',
|
||||
inputType: 'insertText',
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled, "my placeholder");
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
screen.getByRole("textbox").innerHTML = "f";
|
||||
fireEvent.input(screen.getByRole("textbox"), {
|
||||
data: "f",
|
||||
inputType: "insertText",
|
||||
});
|
||||
|
||||
// Then
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('textbox'))
|
||||
.not.toHaveClass("mx_WysiwygComposer_Editor_content_placeholder"),
|
||||
expect(screen.getByRole("textbox")).not.toHaveClass(
|
||||
"mx_WysiwygComposer_Editor_content_placeholder",
|
||||
),
|
||||
);
|
||||
|
||||
// When
|
||||
screen.getByRole('textbox').innerHTML = '';
|
||||
fireEvent.input(screen.getByRole('textbox'), {
|
||||
inputType: 'deleteContentBackward',
|
||||
screen.getByRole("textbox").innerHTML = "";
|
||||
fireEvent.input(screen.getByRole("textbox"), {
|
||||
inputType: "deleteContentBackward",
|
||||
});
|
||||
|
||||
// Then
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('textbox')).toHaveClass("mx_WysiwygComposer_Editor_content_placeholder"),
|
||||
expect(screen.getByRole("textbox")).toHaveClass("mx_WysiwygComposer_Editor_content_placeholder"),
|
||||
);
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
describe.each([
|
||||
{ isRichTextEnabled: true },
|
||||
{ isRichTextEnabled: false },
|
||||
])('Emoji when %s', ({ isRichTextEnabled }) => {
|
||||
let emojiButton: HTMLElement;
|
||||
describe.each([{ isRichTextEnabled: true }, { isRichTextEnabled: false }])(
|
||||
"Emoji when %s",
|
||||
({ isRichTextEnabled }) => {
|
||||
let emojiButton: HTMLElement;
|
||||
|
||||
beforeEach(async () => {
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
emojiButton = screen.getByLabelText('Emoji');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('Should add an emoji in an empty composer', async () => {
|
||||
// When
|
||||
emojiButton.click();
|
||||
|
||||
// Then
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveTextContent(/🦫/));
|
||||
});
|
||||
|
||||
it('Should add an emoji in the middle of a word', async () => {
|
||||
// When
|
||||
screen.getByRole('textbox').focus();
|
||||
screen.getByRole('textbox').innerHTML = 'word';
|
||||
fireEvent.input(screen.getByRole('textbox'), {
|
||||
data: 'word',
|
||||
inputType: 'insertText',
|
||||
beforeEach(async () => {
|
||||
customRender(jest.fn(), jest.fn(), false, isRichTextEnabled);
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
emojiButton = screen.getByLabelText("Emoji");
|
||||
});
|
||||
|
||||
const textNode = screen.getByRole('textbox').firstChild;
|
||||
setSelection({
|
||||
anchorNode: textNode,
|
||||
anchorOffset: 2,
|
||||
focusNode: textNode,
|
||||
focusOffset: 2,
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
// the event is not automatically fired by jest
|
||||
document.dispatchEvent(new CustomEvent('selectionchange'));
|
||||
|
||||
emojiButton.click();
|
||||
it("Should add an emoji in an empty composer", async () => {
|
||||
// When
|
||||
emojiButton.click();
|
||||
|
||||
// Then
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveTextContent(/wo🦫rd/));
|
||||
});
|
||||
});
|
||||
// Then
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveTextContent(/🦫/));
|
||||
});
|
||||
|
||||
it("Should add an emoji in the middle of a word", async () => {
|
||||
// When
|
||||
screen.getByRole("textbox").focus();
|
||||
screen.getByRole("textbox").innerHTML = "word";
|
||||
fireEvent.input(screen.getByRole("textbox"), {
|
||||
data: "word",
|
||||
inputType: "insertText",
|
||||
});
|
||||
|
||||
const textNode = screen.getByRole("textbox").firstChild;
|
||||
setSelection({
|
||||
anchorNode: textNode,
|
||||
anchorOffset: 2,
|
||||
focusNode: textNode,
|
||||
focusOffset: 2,
|
||||
});
|
||||
// the event is not automatically fired by jest
|
||||
document.dispatchEvent(new CustomEvent("selectionchange"));
|
||||
|
||||
emojiButton.click();
|
||||
|
||||
// Then
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveTextContent(/wo🦫rd/));
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -14,15 +14,14 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { AllActionStates, FormattingFunctions } from '@matrix-org/matrix-wysiwyg';
|
||||
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 { FormattingButtons } from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/FormattingButtons";
|
||||
|
||||
describe('FormattingButtons', () => {
|
||||
describe("FormattingButtons", () => {
|
||||
const wysiwyg = {
|
||||
bold: jest.fn(),
|
||||
italic: jest.fn(),
|
||||
|
@ -32,37 +31,37 @@ describe('FormattingButtons', () => {
|
|||
} as unknown as FormattingFunctions;
|
||||
|
||||
const actionStates = {
|
||||
bold: 'reversed',
|
||||
italic: 'reversed',
|
||||
underline: 'enabled',
|
||||
strikeThrough: 'enabled',
|
||||
inlineCode: 'enabled',
|
||||
bold: "reversed",
|
||||
italic: "reversed",
|
||||
underline: "enabled",
|
||||
strikeThrough: "enabled",
|
||||
inlineCode: "enabled",
|
||||
} as AllActionStates;
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('Should have the correspond CSS classes', () => {
|
||||
it("Should have the correspond CSS classes", () => {
|
||||
// When
|
||||
render(<FormattingButtons composer={wysiwyg} actionStates={actionStates} />);
|
||||
|
||||
// Then
|
||||
expect(screen.getByLabelText('Bold')).toHaveClass('mx_FormattingButtons_active');
|
||||
expect(screen.getByLabelText('Italic')).toHaveClass('mx_FormattingButtons_active');
|
||||
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("Bold")).toHaveClass("mx_FormattingButtons_active");
|
||||
expect(screen.getByLabelText("Italic")).toHaveClass("mx_FormattingButtons_active");
|
||||
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");
|
||||
});
|
||||
|
||||
it('Should call wysiwyg function on button click', () => {
|
||||
it("Should call wysiwyg function on button click", () => {
|
||||
// When
|
||||
render(<FormattingButtons composer={wysiwyg} actionStates={actionStates} />);
|
||||
screen.getByLabelText('Bold').click();
|
||||
screen.getByLabelText('Italic').click();
|
||||
screen.getByLabelText('Underline').click();
|
||||
screen.getByLabelText('Strikethrough').click();
|
||||
screen.getByLabelText('Code').click();
|
||||
screen.getByLabelText("Bold").click();
|
||||
screen.getByLabelText("Italic").click();
|
||||
screen.getByLabelText("Underline").click();
|
||||
screen.getByLabelText("Strikethrough").click();
|
||||
screen.getByLabelText("Code").click();
|
||||
|
||||
// Then
|
||||
expect(wysiwyg.bold).toHaveBeenCalledTimes(1);
|
||||
|
@ -72,29 +71,29 @@ describe('FormattingButtons', () => {
|
|||
expect(wysiwyg.inlineCode).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Should display the tooltip on mouse over', async () => {
|
||||
it("Should display the tooltip on mouse over", async () => {
|
||||
// When
|
||||
const user = userEvent.setup();
|
||||
render(<FormattingButtons composer={wysiwyg} actionStates={actionStates} />);
|
||||
await user.hover(screen.getByLabelText('Bold'));
|
||||
await user.hover(screen.getByLabelText("Bold"));
|
||||
|
||||
// Then
|
||||
expect(await screen.findByText('Bold')).toBeTruthy();
|
||||
expect(await screen.findByText("Bold")).toBeTruthy();
|
||||
});
|
||||
|
||||
it('Should not have hover style when active', async () => {
|
||||
it("Should not have hover style when active", async () => {
|
||||
// When
|
||||
const user = userEvent.setup();
|
||||
render(<FormattingButtons composer={wysiwyg} actionStates={actionStates} />);
|
||||
await user.hover(screen.getByLabelText('Bold'));
|
||||
await user.hover(screen.getByLabelText("Bold"));
|
||||
|
||||
// Then
|
||||
expect(screen.getByLabelText('Bold')).not.toHaveClass('mx_FormattingButtons_Button_hover');
|
||||
expect(screen.getByLabelText("Bold")).not.toHaveClass("mx_FormattingButtons_Button_hover");
|
||||
|
||||
// When
|
||||
await user.hover(screen.getByLabelText('Underline'));
|
||||
await user.hover(screen.getByLabelText("Underline"));
|
||||
|
||||
// Then
|
||||
expect(screen.getByLabelText('Underline')).toHaveClass('mx_FormattingButtons_Button_hover');
|
||||
expect(screen.getByLabelText("Underline")).toHaveClass("mx_FormattingButtons_Button_hover");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -14,84 +14,89 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
|
||||
import { PlainTextComposer }
|
||||
from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer";
|
||||
import { PlainTextComposer } from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/PlainTextComposer";
|
||||
|
||||
describe('PlainTextComposer', () => {
|
||||
describe("PlainTextComposer", () => {
|
||||
const customRender = (
|
||||
onChange = (_content: string) => void 0,
|
||||
onSend = () => void 0,
|
||||
disabled = false,
|
||||
initialContent?: string) => {
|
||||
initialContent?: string,
|
||||
) => {
|
||||
return render(
|
||||
<PlainTextComposer onChange={onChange} onSend={onSend} disabled={disabled} initialContent={initialContent} />,
|
||||
<PlainTextComposer
|
||||
onChange={onChange}
|
||||
onSend={onSend}
|
||||
disabled={disabled}
|
||||
initialContent={initialContent}
|
||||
/>,
|
||||
);
|
||||
};
|
||||
|
||||
it('Should have contentEditable at false when disabled', () => {
|
||||
it("Should have contentEditable at false when disabled", () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), true);
|
||||
|
||||
// Then
|
||||
expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "false");
|
||||
expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "false");
|
||||
});
|
||||
|
||||
it('Should have focus', () => {
|
||||
it("Should have focus", () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), false);
|
||||
|
||||
// Then
|
||||
expect(screen.getByRole('textbox')).toHaveFocus();
|
||||
expect(screen.getByRole("textbox")).toHaveFocus();
|
||||
});
|
||||
|
||||
it('Should call onChange handler', async () => {
|
||||
it("Should call onChange handler", async () => {
|
||||
// When
|
||||
const content = 'content';
|
||||
const content = "content";
|
||||
const onChange = jest.fn();
|
||||
customRender(onChange, jest.fn());
|
||||
await userEvent.type(screen.getByRole('textbox'), content);
|
||||
await userEvent.type(screen.getByRole("textbox"), content);
|
||||
|
||||
// Then
|
||||
expect(onChange).toBeCalledWith(content);
|
||||
});
|
||||
|
||||
it('Should call onSend when Enter is pressed', async () => {
|
||||
it("Should call onSend when Enter is pressed", async () => {
|
||||
//When
|
||||
const onSend = jest.fn();
|
||||
customRender(jest.fn(), onSend);
|
||||
await userEvent.type(screen.getByRole('textbox'), '{enter}');
|
||||
await userEvent.type(screen.getByRole("textbox"), "{enter}");
|
||||
|
||||
// Then it sends a message
|
||||
expect(onSend).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Should clear textbox content when clear is called', async () => {
|
||||
it("Should clear textbox content when clear is called", async () => {
|
||||
//When
|
||||
let composer;
|
||||
render(
|
||||
<PlainTextComposer onChange={jest.fn()} onSend={jest.fn()}>
|
||||
{ (ref, composerFunctions) => {
|
||||
{(ref, composerFunctions) => {
|
||||
composer = composerFunctions;
|
||||
return null;
|
||||
} }
|
||||
}}
|
||||
</PlainTextComposer>,
|
||||
);
|
||||
await userEvent.type(screen.getByRole('textbox'), 'content');
|
||||
expect(screen.getByRole('textbox').innerHTML).toBe('content');
|
||||
await userEvent.type(screen.getByRole("textbox"), "content");
|
||||
expect(screen.getByRole("textbox").innerHTML).toBe("content");
|
||||
composer.clear();
|
||||
|
||||
// Then
|
||||
expect(screen.getByRole('textbox').innerHTML).toBeFalsy();
|
||||
expect(screen.getByRole("textbox").innerHTML).toBeFalsy();
|
||||
});
|
||||
|
||||
it('Should have data-is-expanded when it has two lines', async () => {
|
||||
it("Should have data-is-expanded when it has two lines", async () => {
|
||||
let resizeHandler: ResizeObserverCallback = jest.fn();
|
||||
let editor: Element | null = null;
|
||||
jest.spyOn(global, 'ResizeObserver').mockImplementation((handler) => {
|
||||
jest.spyOn(global, "ResizeObserver").mockImplementation((handler) => {
|
||||
resizeHandler = handler;
|
||||
return {
|
||||
observe: (element) => {
|
||||
|
@ -100,21 +105,18 @@ describe('PlainTextComposer', () => {
|
|||
unobserve: jest.fn(),
|
||||
disconnect: jest.fn(),
|
||||
};
|
||||
},
|
||||
);
|
||||
jest.spyOn(global, 'requestAnimationFrame').mockImplementation(cb => {
|
||||
});
|
||||
jest.spyOn(global, "requestAnimationFrame").mockImplementation((cb) => {
|
||||
cb(0);
|
||||
return 0;
|
||||
});
|
||||
|
||||
//When
|
||||
render(
|
||||
<PlainTextComposer onChange={jest.fn()} onSend={jest.fn()} />,
|
||||
);
|
||||
render(<PlainTextComposer onChange={jest.fn()} onSend={jest.fn()} />);
|
||||
|
||||
// Then
|
||||
expect(screen.getByTestId('WysiwygComposerEditor').attributes['data-is-expanded'].value).toBe('false');
|
||||
expect(editor).toBe(screen.getByRole('textbox'));
|
||||
expect(screen.getByTestId("WysiwygComposerEditor").attributes["data-is-expanded"].value).toBe("false");
|
||||
expect(editor).toBe(screen.getByRole("textbox"));
|
||||
|
||||
// When
|
||||
resizeHandler(
|
||||
|
@ -124,7 +126,7 @@ describe('PlainTextComposer', () => {
|
|||
jest.runAllTimers();
|
||||
|
||||
// Then
|
||||
expect(screen.getByTestId('WysiwygComposerEditor').attributes['data-is-expanded'].value).toBe('true');
|
||||
expect(screen.getByTestId("WysiwygComposerEditor").attributes["data-is-expanded"].value).toBe("true");
|
||||
|
||||
(global.ResizeObserver as jest.Mock).mockRestore();
|
||||
(global.requestAnimationFrame as jest.Mock).mockRestore();
|
||||
|
|
|
@ -18,35 +18,35 @@ import "@testing-library/jest-dom";
|
|||
import React from "react";
|
||||
import { fireEvent, render, screen, waitFor } from "@testing-library/react";
|
||||
|
||||
import { WysiwygComposer }
|
||||
from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/WysiwygComposer";
|
||||
import { WysiwygComposer } from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/WysiwygComposer";
|
||||
import SettingsStore from "../../../../../../src/settings/SettingsStore";
|
||||
|
||||
describe('WysiwygComposer', () => {
|
||||
describe("WysiwygComposer", () => {
|
||||
const customRender = (
|
||||
onChange = (_content: string) => void 0,
|
||||
onSend = () => void 0,
|
||||
disabled = false,
|
||||
initialContent?: string) => {
|
||||
initialContent?: string,
|
||||
) => {
|
||||
return render(
|
||||
<WysiwygComposer onChange={onChange} onSend={onSend} disabled={disabled} initialContent={initialContent} />,
|
||||
);
|
||||
};
|
||||
|
||||
it('Should have contentEditable at false when disabled', () => {
|
||||
it("Should have contentEditable at false when disabled", () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), true);
|
||||
|
||||
// Then
|
||||
expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "false");
|
||||
expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "false");
|
||||
});
|
||||
|
||||
describe('Standard behavior', () => {
|
||||
describe("Standard behavior", () => {
|
||||
const onChange = jest.fn();
|
||||
const onSend = jest.fn();
|
||||
beforeEach(async () => {
|
||||
customRender(onChange, onSend);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -54,39 +54,42 @@ describe('WysiwygComposer', () => {
|
|||
onSend.mockReset();
|
||||
});
|
||||
|
||||
it('Should have contentEditable at true', async () => {
|
||||
it("Should have contentEditable at true", async () => {
|
||||
// Then
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
});
|
||||
|
||||
it('Should have focus', async () => {
|
||||
it("Should have focus", async () => {
|
||||
// Then
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveFocus());
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveFocus());
|
||||
});
|
||||
|
||||
it('Should call onChange handler', async () => {
|
||||
it("Should call onChange handler", async () => {
|
||||
// When
|
||||
fireEvent.input(screen.getByRole('textbox'), {
|
||||
data: 'foo bar',
|
||||
inputType: 'insertText',
|
||||
fireEvent.input(screen.getByRole("textbox"), {
|
||||
data: "foo bar",
|
||||
inputType: "insertText",
|
||||
});
|
||||
|
||||
// Then
|
||||
await waitFor(() => expect(onChange).toBeCalledWith('foo bar'));
|
||||
await waitFor(() => expect(onChange).toBeCalledWith("foo bar"));
|
||||
});
|
||||
|
||||
it('Should call onSend when Enter is pressed ', async () => {
|
||||
//When
|
||||
fireEvent(screen.getByRole('textbox'), new InputEvent('input', {
|
||||
inputType: "insertParagraph",
|
||||
}));
|
||||
it("Should call onSend when Enter is pressed ", async () => {
|
||||
//When
|
||||
fireEvent(
|
||||
screen.getByRole("textbox"),
|
||||
new InputEvent("input", {
|
||||
inputType: "insertParagraph",
|
||||
}),
|
||||
);
|
||||
|
||||
// Then it sends a message
|
||||
await waitFor(() => expect(onSend).toBeCalledTimes(1));
|
||||
});
|
||||
});
|
||||
|
||||
describe('When settings require Ctrl+Enter to send', () => {
|
||||
describe("When settings require Ctrl+Enter to send", () => {
|
||||
const onChange = jest.fn();
|
||||
const onSend = jest.fn();
|
||||
beforeEach(async () => {
|
||||
|
@ -94,7 +97,7 @@ describe('WysiwygComposer', () => {
|
|||
if (name === "MessageComposerInput.ctrlEnterToSend") return true;
|
||||
});
|
||||
customRender(onChange, onSend);
|
||||
await waitFor(() => expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "true"));
|
||||
await waitFor(() => expect(screen.getByRole("textbox")).toHaveAttribute("contentEditable", "true"));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -102,25 +105,30 @@ describe('WysiwygComposer', () => {
|
|||
onSend.mockReset();
|
||||
});
|
||||
|
||||
it('Should not call onSend when Enter is pressed', async () => {
|
||||
it("Should not call onSend when Enter is pressed", async () => {
|
||||
// When
|
||||
fireEvent(screen.getByRole('textbox'), new InputEvent('input', {
|
||||
inputType: "insertParagraph",
|
||||
}));
|
||||
fireEvent(
|
||||
screen.getByRole("textbox"),
|
||||
new InputEvent("input", {
|
||||
inputType: "insertParagraph",
|
||||
}),
|
||||
);
|
||||
|
||||
// Then it does not send a message
|
||||
await waitFor(() => expect(onSend).toBeCalledTimes(0));
|
||||
});
|
||||
|
||||
it('Should send a message when Ctrl+Enter is pressed', async () => {
|
||||
it("Should send a message when Ctrl+Enter is pressed", async () => {
|
||||
// When
|
||||
fireEvent(screen.getByRole('textbox'), new InputEvent('input', {
|
||||
inputType: "sendMessage",
|
||||
}));
|
||||
fireEvent(
|
||||
screen.getByRole("textbox"),
|
||||
new InputEvent("input", {
|
||||
inputType: "sendMessage",
|
||||
}),
|
||||
);
|
||||
|
||||
// Then it sends a message
|
||||
await waitFor(() => expect(onSend).toBeCalledTimes(1));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -16,21 +16,20 @@ limitations under the License.
|
|||
|
||||
import { mkEvent } from "../../../../../test-utils";
|
||||
import { RoomPermalinkCreator } from "../../../../../../src/utils/permalinks/Permalinks";
|
||||
import { createMessageContent }
|
||||
from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/createMessageContent";
|
||||
import { createMessageContent } from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/createMessageContent";
|
||||
|
||||
describe('createMessageContent', () => {
|
||||
describe("createMessageContent", () => {
|
||||
const permalinkCreator = {
|
||||
forEvent(eventId: string): string {
|
||||
return "$$permalink$$";
|
||||
},
|
||||
} as RoomPermalinkCreator;
|
||||
const message = '<i><b>hello</b> world</i>';
|
||||
const message = "<i><b>hello</b> world</i>";
|
||||
const mockEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
content: { "msgtype": "m.text", "body": "Replying to this" },
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser",
|
||||
content: { msgtype: "m.text", body: "Replying to this" },
|
||||
event: true,
|
||||
});
|
||||
|
||||
|
@ -44,14 +43,14 @@ describe('createMessageContent', () => {
|
|||
|
||||
// Then
|
||||
expect(content).toEqual({
|
||||
"body": "hello world",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": message,
|
||||
"msgtype": "m.text",
|
||||
body: "hello world",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: message,
|
||||
msgtype: "m.text",
|
||||
});
|
||||
});
|
||||
|
||||
it('Should add reply to message content', () => {
|
||||
it("Should add reply to message content", () => {
|
||||
// When
|
||||
const content = createMessageContent(message, true, { permalinkCreator, replyToEvent: mockEvent });
|
||||
|
||||
|
@ -59,13 +58,14 @@ describe('createMessageContent', () => {
|
|||
expect(content).toEqual({
|
||||
"body": "> <myfakeuser> Replying to this\n\nhello world",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": "<mx-reply><blockquote><a href=\"$$permalink$$\">In reply to</a>" +
|
||||
" <a href=\"https://matrix.to/#/myfakeuser\">myfakeuser</a>"+
|
||||
"<br>Replying to this</blockquote></mx-reply><i><b>hello</b> world</i>",
|
||||
"formatted_body":
|
||||
'<mx-reply><blockquote><a href="$$permalink$$">In reply to</a>' +
|
||||
' <a href="https://matrix.to/#/myfakeuser">myfakeuser</a>' +
|
||||
"<br>Replying to this</blockquote></mx-reply><i><b>hello</b> world</i>",
|
||||
"msgtype": "m.text",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": mockEvent.getId(),
|
||||
event_id: mockEvent.getId(),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -86,31 +86,31 @@ describe('createMessageContent', () => {
|
|||
"formatted_body": message,
|
||||
"msgtype": "m.text",
|
||||
"m.relates_to": {
|
||||
"event_id": "myFakeThreadId",
|
||||
"rel_type": "m.thread",
|
||||
event_id: "myFakeThreadId",
|
||||
rel_type: "m.thread",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('Should add fields related to edition', () => {
|
||||
it("Should add fields related to edition", () => {
|
||||
// When
|
||||
const editedEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser2',
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser2",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "First message",
|
||||
"formatted_body": "<b>First Message</b>",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": 'eventId',
|
||||
event_id: "eventId",
|
||||
},
|
||||
} },
|
||||
},
|
||||
},
|
||||
event: true,
|
||||
});
|
||||
const content =
|
||||
createMessageContent(message, true, { permalinkCreator, editedEvent });
|
||||
const content = createMessageContent(message, true, { permalinkCreator, editedEvent });
|
||||
|
||||
// Then
|
||||
expect(content).toEqual({
|
||||
|
@ -119,14 +119,14 @@ describe('createMessageContent', () => {
|
|||
"formatted_body": ` * ${message}`,
|
||||
"msgtype": "m.text",
|
||||
"m.new_content": {
|
||||
"body": "hello world",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": message,
|
||||
"msgtype": "m.text",
|
||||
body: "hello world",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: message,
|
||||
msgtype: "m.text",
|
||||
},
|
||||
"m.relates_to": {
|
||||
"event_id": editedEvent.getId(),
|
||||
"rel_type": "m.replace",
|
||||
event_id: editedEvent.getId(),
|
||||
rel_type: "m.replace",
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,40 +17,38 @@ limitations under the License.
|
|||
import { EventStatus } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import { IRoomState } from "../../../../../../src/components/structures/RoomView";
|
||||
import { editMessage, sendMessage }
|
||||
from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/message";
|
||||
import { editMessage, sendMessage } from "../../../../../../src/components/views/rooms/wysiwyg_composer/utils/message";
|
||||
import { createTestClient, getRoomContext, mkEvent, mkStubRoom } from "../../../../../test-utils";
|
||||
import defaultDispatcher from "../../../../../../src/dispatcher/dispatcher";
|
||||
import SettingsStore from "../../../../../../src/settings/SettingsStore";
|
||||
import { SettingLevel } from "../../../../../../src/settings/SettingLevel";
|
||||
import { RoomPermalinkCreator } from "../../../../../../src/utils/permalinks/Permalinks";
|
||||
import EditorStateTransfer from "../../../../../../src/utils/EditorStateTransfer";
|
||||
import * as ConfirmRedactDialog
|
||||
from "../../../../../../src/components/views/dialogs/ConfirmRedactDialog";
|
||||
import * as ConfirmRedactDialog from "../../../../../../src/components/views/dialogs/ConfirmRedactDialog";
|
||||
|
||||
describe('message', () => {
|
||||
describe("message", () => {
|
||||
const permalinkCreator = {
|
||||
forEvent(eventId: string): string {
|
||||
return "$$permalink$$";
|
||||
},
|
||||
} as RoomPermalinkCreator;
|
||||
const message = '<i><b>hello</b> world</i>';
|
||||
const message = "<i><b>hello</b> world</i>";
|
||||
const mockEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser",
|
||||
content: {
|
||||
"msgtype": "m.text",
|
||||
"body": "Replying to this",
|
||||
"format": 'org.matrix.custom.html',
|
||||
"formatted_body": 'Replying to this',
|
||||
msgtype: "m.text",
|
||||
body: "Replying to this",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: "Replying to this",
|
||||
},
|
||||
event: true,
|
||||
});
|
||||
|
||||
const mockClient = createTestClient();
|
||||
const mockRoom = mkStubRoom('myfakeroom', 'myfakeroom', mockClient) as any;
|
||||
mockRoom.findEventById = jest.fn(eventId => {
|
||||
const mockRoom = mkStubRoom("myfakeroom", "myfakeroom", mockClient) as any;
|
||||
mockRoom.findEventById = jest.fn((eventId) => {
|
||||
return eventId === mockEvent.getId() ? mockEvent : null;
|
||||
});
|
||||
|
||||
|
@ -62,41 +60,41 @@ describe('message', () => {
|
|||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe('sendMessage', () => {
|
||||
it('Should not send empty html message', async () => {
|
||||
describe("sendMessage", () => {
|
||||
it("Should not send empty html message", async () => {
|
||||
// When
|
||||
await sendMessage('', true, { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator });
|
||||
await sendMessage("", true, { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator });
|
||||
|
||||
// Then
|
||||
expect(mockClient.sendMessage).toBeCalledTimes(0);
|
||||
expect(spyDispatcher).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Should send html message', async () => {
|
||||
it("Should send html message", async () => {
|
||||
// When
|
||||
await sendMessage(
|
||||
message,
|
||||
true,
|
||||
{ roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator },
|
||||
);
|
||||
await sendMessage(message, true, {
|
||||
roomContext: defaultRoomContext,
|
||||
mxClient: mockClient,
|
||||
permalinkCreator,
|
||||
});
|
||||
|
||||
// Then
|
||||
const expectedContent = {
|
||||
"body": "hello world",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": "<i><b>hello</b> world</i>",
|
||||
"msgtype": "m.text",
|
||||
body: "hello world",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: "<i><b>hello</b> world</i>",
|
||||
msgtype: "m.text",
|
||||
};
|
||||
expect(mockClient.sendMessage).toBeCalledWith('myfakeroom', null, expectedContent);
|
||||
expect(spyDispatcher).toBeCalledWith({ action: 'message_sent' });
|
||||
expect(mockClient.sendMessage).toBeCalledWith("myfakeroom", null, expectedContent);
|
||||
expect(spyDispatcher).toBeCalledWith({ action: "message_sent" });
|
||||
});
|
||||
|
||||
it('Should send reply to html message', async () => {
|
||||
it("Should send reply to html message", async () => {
|
||||
const mockReplyEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser2',
|
||||
content: { "msgtype": "m.text", "body": "My reply" },
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser2",
|
||||
content: { msgtype: "m.text", body: "My reply" },
|
||||
event: true,
|
||||
});
|
||||
|
||||
|
@ -110,7 +108,7 @@ describe('message', () => {
|
|||
|
||||
// Then
|
||||
expect(spyDispatcher).toBeCalledWith({
|
||||
action: 'reply_to_event',
|
||||
action: "reply_to_event",
|
||||
event: null,
|
||||
context: defaultRoomContext.timelineRenderingType,
|
||||
});
|
||||
|
@ -118,75 +116,71 @@ describe('message', () => {
|
|||
const expectedContent = {
|
||||
"body": "> <myfakeuser2> My reply\n\nhello world",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": "<mx-reply><blockquote><a href=\"$$permalink$$\">In reply to</a>" +
|
||||
" <a href=\"https://matrix.to/#/myfakeuser2\">myfakeuser2</a>" +
|
||||
"<br>My reply</blockquote></mx-reply><i><b>hello</b> world</i>",
|
||||
"formatted_body":
|
||||
'<mx-reply><blockquote><a href="$$permalink$$">In reply to</a>' +
|
||||
' <a href="https://matrix.to/#/myfakeuser2">myfakeuser2</a>' +
|
||||
"<br>My reply</blockquote></mx-reply><i><b>hello</b> world</i>",
|
||||
"msgtype": "m.text",
|
||||
"m.relates_to": {
|
||||
"m.in_reply_to": {
|
||||
"event_id": mockReplyEvent.getId(),
|
||||
event_id: mockReplyEvent.getId(),
|
||||
},
|
||||
},
|
||||
};
|
||||
expect(mockClient.sendMessage).toBeCalledWith('myfakeroom', null, expectedContent);
|
||||
expect(mockClient.sendMessage).toBeCalledWith("myfakeroom", null, expectedContent);
|
||||
});
|
||||
|
||||
it('Should scroll to bottom after sending a html message', async () => {
|
||||
it("Should scroll to bottom after sending a html message", async () => {
|
||||
// When
|
||||
SettingsStore.setValue("scrollToBottomOnMessageSent", null, SettingLevel.DEVICE, true);
|
||||
await sendMessage(
|
||||
message,
|
||||
true,
|
||||
{ roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator },
|
||||
);
|
||||
await sendMessage(message, true, {
|
||||
roomContext: defaultRoomContext,
|
||||
mxClient: mockClient,
|
||||
permalinkCreator,
|
||||
});
|
||||
|
||||
// Then
|
||||
expect(spyDispatcher).toBeCalledWith(
|
||||
{ action: 'scroll_to_bottom', timelineRenderingType: defaultRoomContext.timelineRenderingType },
|
||||
);
|
||||
expect(spyDispatcher).toBeCalledWith({
|
||||
action: "scroll_to_bottom",
|
||||
timelineRenderingType: defaultRoomContext.timelineRenderingType,
|
||||
});
|
||||
});
|
||||
|
||||
it('Should handle emojis', async () => {
|
||||
it("Should handle emojis", async () => {
|
||||
// When
|
||||
await sendMessage(
|
||||
'🎉',
|
||||
false,
|
||||
{ roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator },
|
||||
);
|
||||
await sendMessage("🎉", false, { roomContext: defaultRoomContext, mxClient: mockClient, permalinkCreator });
|
||||
|
||||
// Then
|
||||
expect(spyDispatcher).toBeCalledWith(
|
||||
{ action: 'effects.confetti' },
|
||||
);
|
||||
expect(spyDispatcher).toBeCalledWith({ action: "effects.confetti" });
|
||||
});
|
||||
});
|
||||
|
||||
describe('editMessage', () => {
|
||||
describe("editMessage", () => {
|
||||
const editorStateTransfer = new EditorStateTransfer(mockEvent);
|
||||
|
||||
it('Should cancel editing and ask for event removal when message is empty', async () => {
|
||||
it("Should cancel editing and ask for event removal when message is empty", async () => {
|
||||
// When
|
||||
const mockCreateRedactEventDialog = jest.spyOn(ConfirmRedactDialog, 'createRedactEventDialog');
|
||||
const mockCreateRedactEventDialog = jest.spyOn(ConfirmRedactDialog, "createRedactEventDialog");
|
||||
|
||||
const mockEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
content: { "msgtype": "m.text", "body": "Replying to this" },
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser",
|
||||
content: { msgtype: "m.text", body: "Replying to this" },
|
||||
event: true,
|
||||
});
|
||||
const replacingEvent = mkEvent({
|
||||
type: "m.room.message",
|
||||
room: 'myfakeroom',
|
||||
user: 'myfakeuser',
|
||||
content: { "msgtype": "m.text", "body": "ReplacingEvent" },
|
||||
room: "myfakeroom",
|
||||
user: "myfakeuser",
|
||||
content: { msgtype: "m.text", body: "ReplacingEvent" },
|
||||
event: true,
|
||||
});
|
||||
replacingEvent.setStatus(EventStatus.QUEUED);
|
||||
mockEvent.makeReplaced(replacingEvent);
|
||||
const editorStateTransfer = new EditorStateTransfer(mockEvent);
|
||||
|
||||
await editMessage('', { roomContext: defaultRoomContext, mxClient: mockClient, editorStateTransfer });
|
||||
await editMessage("", { roomContext: defaultRoomContext, mxClient: mockClient, editorStateTransfer });
|
||||
|
||||
// Then
|
||||
expect(mockClient.sendMessage).toBeCalledTimes(0);
|
||||
|
@ -195,22 +189,26 @@ describe('message', () => {
|
|||
expect(spyDispatcher).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Should do nothing if the content is unmodified', async () => {
|
||||
it("Should do nothing if the content is unmodified", async () => {
|
||||
// When
|
||||
await editMessage(
|
||||
mockEvent.getContent().body,
|
||||
{ roomContext: defaultRoomContext, mxClient: mockClient, editorStateTransfer });
|
||||
await editMessage(mockEvent.getContent().body, {
|
||||
roomContext: defaultRoomContext,
|
||||
mxClient: mockClient,
|
||||
editorStateTransfer,
|
||||
});
|
||||
|
||||
// Then
|
||||
expect(mockClient.sendMessage).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Should send a message when the content is modified', async () => {
|
||||
it("Should send a message when the content is modified", async () => {
|
||||
// When
|
||||
const newMessage = `${mockEvent.getContent().body} new content`;
|
||||
await editMessage(
|
||||
newMessage,
|
||||
{ roomContext: defaultRoomContext, mxClient: mockClient, editorStateTransfer });
|
||||
await editMessage(newMessage, {
|
||||
roomContext: defaultRoomContext,
|
||||
mxClient: mockClient,
|
||||
editorStateTransfer,
|
||||
});
|
||||
|
||||
// Then
|
||||
const { msgtype, format } = mockEvent.getContent();
|
||||
|
@ -218,20 +216,20 @@ describe('message', () => {
|
|||
"body": ` * ${newMessage}`,
|
||||
"formatted_body": ` * ${newMessage}`,
|
||||
"m.new_content": {
|
||||
"body": "Replying to this new content",
|
||||
"format": "org.matrix.custom.html",
|
||||
"formatted_body": "Replying to this new content",
|
||||
"msgtype": "m.text",
|
||||
body: "Replying to this new content",
|
||||
format: "org.matrix.custom.html",
|
||||
formatted_body: "Replying to this new content",
|
||||
msgtype: "m.text",
|
||||
},
|
||||
"m.relates_to": {
|
||||
"event_id": mockEvent.getId(),
|
||||
"rel_type": "m.replace",
|
||||
event_id: mockEvent.getId(),
|
||||
rel_type: "m.replace",
|
||||
},
|
||||
msgtype,
|
||||
format,
|
||||
};
|
||||
expect(mockClient.sendMessage).toBeCalledWith(mockEvent.getRoomId(), null, expectedContent);
|
||||
expect(spyDispatcher).toBeCalledWith({ action: 'message_sent' });
|
||||
expect(spyDispatcher).toBeCalledWith({ action: "message_sent" });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue