Add new tests for WysiwygComposer
This commit is contained in:
parent
c9bf7da629
commit
50c29502e4
11 changed files with 774 additions and 357 deletions
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
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 { render, screen } from "@testing-library/react";
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import { FormattingButtons }
|
||||
from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/FormattingButtons";
|
||||
|
||||
describe('FormattingButtons', () => {
|
||||
const wysiwyg = {
|
||||
bold: jest.fn(),
|
||||
italic: jest.fn(),
|
||||
underline: jest.fn(),
|
||||
strikeThrough: jest.fn(),
|
||||
} as any;
|
||||
|
||||
const formattingStates = {
|
||||
bold: 'reversed',
|
||||
italic: 'reversed',
|
||||
underline: 'enabled',
|
||||
strikeThrough: 'enabled',
|
||||
} as any;
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
it('Should have the correspond CSS classes', () => {
|
||||
// When
|
||||
render(<FormattingButtons composer={wysiwyg} formattingStates={formattingStates} />);
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
it('Should call wysiwyg function on button click', () => {
|
||||
// When
|
||||
render(<FormattingButtons composer={wysiwyg} formattingStates={formattingStates} />);
|
||||
screen.getByLabelText('Bold').click();
|
||||
screen.getByLabelText('Italic').click();
|
||||
screen.getByLabelText('Underline').click();
|
||||
screen.getByLabelText('Strikethrough').click();
|
||||
|
||||
// Then
|
||||
expect(wysiwyg.bold).toHaveBeenCalledTimes(1);
|
||||
expect(wysiwyg.italic).toHaveBeenCalledTimes(1);
|
||||
expect(wysiwyg.underline).toHaveBeenCalledTimes(1);
|
||||
expect(wysiwyg.strikeThrough).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('Should display the tooltip on mouse over', async () => {
|
||||
// When
|
||||
const user = userEvent.setup();
|
||||
render(<FormattingButtons composer={wysiwyg} formattingStates={formattingStates} />);
|
||||
await user.hover(screen.getByLabelText('Bold'));
|
||||
|
||||
// Then
|
||||
expect(await screen.findByText('Bold')).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,152 @@
|
|||
/*
|
||||
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 "@testing-library/jest-dom";
|
||||
import React from "react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { InputEventProcessor, Wysiwyg, WysiwygProps } from "@matrix-org/matrix-wysiwyg";
|
||||
|
||||
import MatrixClientContext from "../../../../../../src/contexts/MatrixClientContext";
|
||||
import { IRoomState } from "../../../../../../src/components/structures/RoomView";
|
||||
import { createTestClient, getRoomContext, mkEvent, mkStubRoom } from "../../../../../test-utils";
|
||||
import RoomContext from "../../../../../../src/contexts/RoomContext";
|
||||
import { WysiwygComposer }
|
||||
from "../../../../../../src/components/views/rooms/wysiwyg_composer/components/WysiwygComposer";
|
||||
import SettingsStore from "../../../../../../src/settings/SettingsStore";
|
||||
|
||||
// Work around missing ClipboardEvent type
|
||||
class MyClipboardEvent {}
|
||||
window.ClipboardEvent = MyClipboardEvent as any;
|
||||
|
||||
let inputEventProcessor: InputEventProcessor | null = null;
|
||||
|
||||
// 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: (props: WysiwygProps) => {
|
||||
inputEventProcessor = props.inputEventProcessor ?? null;
|
||||
return {
|
||||
ref: { current: null },
|
||||
content: '<b>html</b>',
|
||||
isWysiwygReady: true,
|
||||
wysiwyg: { clear: () => void 0 },
|
||||
formattingStates: {
|
||||
bold: 'enabled',
|
||||
italic: 'enabled',
|
||||
underline: 'enabled',
|
||||
strikeThrough: 'enabled',
|
||||
},
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
describe('WysiwygComposer', () => {
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
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 = getRoomContext(mockRoom, {});
|
||||
|
||||
const customRender = (onChange = (_content: string) => void 0, onSend = () => void 0, disabled = false) => {
|
||||
return render(
|
||||
<MatrixClientContext.Provider value={mockClient}>
|
||||
<RoomContext.Provider value={defaultRoomContext}>
|
||||
<WysiwygComposer onChange={onChange} onSend={onSend} disabled={disabled} />
|
||||
</RoomContext.Provider>
|
||||
</MatrixClientContext.Provider>,
|
||||
);
|
||||
};
|
||||
|
||||
it('Should have contentEditable at false when disabled', () => {
|
||||
// When
|
||||
customRender(jest.fn(), jest.fn(), true);
|
||||
|
||||
// Then
|
||||
expect(screen.getByRole('textbox')).toHaveAttribute('contentEditable', "false");
|
||||
});
|
||||
|
||||
it('Should call onChange handler', (done) => {
|
||||
const html = '<b>html</b>';
|
||||
customRender((content) => {
|
||||
expect(content).toBe((html));
|
||||
done();
|
||||
}, jest.fn());
|
||||
});
|
||||
|
||||
it('Should call onSend when Enter is pressed ', () => {
|
||||
//When
|
||||
const onSend = jest.fn();
|
||||
customRender(jest.fn(), onSend);
|
||||
|
||||
// When we tell its inputEventProcesser that the user pressed Enter
|
||||
const event = new InputEvent("insertParagraph", { inputType: "insertParagraph" });
|
||||
const wysiwyg = { actions: { clear: () => {} } } as Wysiwyg;
|
||||
inputEventProcessor(event, wysiwyg);
|
||||
|
||||
// Then it sends a message
|
||||
expect(onSend).toBeCalledTimes(1);
|
||||
});
|
||||
|
||||
describe('When settings require Ctrl+Enter to send', () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(SettingsStore, "getValue").mockImplementation((name: string) => {
|
||||
if (name === "MessageComposerInput.ctrlEnterToSend") return true;
|
||||
});
|
||||
});
|
||||
|
||||
it('Should not call onSend when Enter is pressed', async () => {
|
||||
// Given a composer
|
||||
const onSend = jest.fn();
|
||||
customRender(() => {}, onSend, false);
|
||||
|
||||
// When we tell its inputEventProcesser that the user pressed Enter
|
||||
const event = new InputEvent("input", { inputType: "insertParagraph" });
|
||||
const wysiwyg = { actions: { clear: () => {} } } as Wysiwyg;
|
||||
inputEventProcessor(event, wysiwyg);
|
||||
|
||||
// Then it does not send a message
|
||||
expect(onSend).toBeCalledTimes(0);
|
||||
});
|
||||
|
||||
it('Should send a message when Ctrl+Enter is pressed', async () => {
|
||||
// Given a composer
|
||||
const onSend = jest.fn();
|
||||
customRender(() => {}, onSend, false);
|
||||
|
||||
// When we tell its inputEventProcesser that the user pressed Ctrl+Enter
|
||||
const event = new InputEvent("input", { inputType: "sendMessage" });
|
||||
const wysiwyg = { actions: { clear: () => {} } } as Wysiwyg;
|
||||
inputEventProcessor(event, wysiwyg);
|
||||
|
||||
// Then it sends a message
|
||||
expect(onSend).toBeCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue