@madie/madie-design-system 1.2.67 → 1.2.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/RichTextEditor/index.jsx +213 -40
- package/components/RichTextEditor/tableIcons/addColumnLeftIcon.jsx +20 -0
- package/components/RichTextEditor/tableIcons/addColumnRightIcon.jsx +20 -0
- package/components/RichTextEditor/tableIcons/addRowAboveIcon.jsx +20 -0
- package/components/RichTextEditor/tableIcons/addRowBelowIcon.jsx +20 -0
- package/components/RichTextEditor/tableIcons/deleteColumnIcon.jsx +20 -0
- package/components/RichTextEditor/tableIcons/deleteRowIcon.jsx +20 -0
- package/components/RichTextEditor/tableIcons/deleteTableIcon.jsx +24 -0
- package/components/RichTextEditor/tableIcons/tabelIconsIndex.js +17 -0
- package/dist/browser.js +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.js +7 -7
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/test/components/RichTextEditor.test.js +218 -2
package/package.json
CHANGED
|
@@ -1,8 +1,36 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
3
4
|
import RichTextEditor from "../../components/RichTextEditor/index";
|
|
4
5
|
import DOMPurify from "dompurify";
|
|
5
6
|
|
|
7
|
+
beforeAll(() => {
|
|
8
|
+
Element.prototype.getClientRects = jest.fn(() => [{
|
|
9
|
+
top: 0,
|
|
10
|
+
left: 0,
|
|
11
|
+
bottom: 0,
|
|
12
|
+
right: 0,
|
|
13
|
+
width: 0,
|
|
14
|
+
height: 0
|
|
15
|
+
}]);
|
|
16
|
+
|
|
17
|
+
Element.prototype.scrollIntoView = jest.fn();
|
|
18
|
+
|
|
19
|
+
window.getSelection = jest.fn(() => ({
|
|
20
|
+
removeAllRanges: jest.fn(),
|
|
21
|
+
addRange: jest.fn(),
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
Element.prototype.getBoundingClientRect = jest.fn(() => ({
|
|
25
|
+
top: 0,
|
|
26
|
+
left: 0,
|
|
27
|
+
bottom: 0,
|
|
28
|
+
right: 0,
|
|
29
|
+
width: 0,
|
|
30
|
+
height: 0
|
|
31
|
+
}));
|
|
32
|
+
});
|
|
33
|
+
|
|
6
34
|
describe("RichTextEditor Component", () => {
|
|
7
35
|
const mockOnChange = jest.fn();
|
|
8
36
|
|
|
@@ -92,10 +120,10 @@ describe("RichTextEditor Component", () => {
|
|
|
92
120
|
|
|
93
121
|
it("test renders sanitized content with preserved whitespace when readOnly is true", () => {
|
|
94
122
|
const content = `this is a statement
|
|
95
|
-
this is a statement
|
|
123
|
+
this is a statement
|
|
96
124
|
this is a statement
|
|
97
125
|
|
|
98
|
-
---------------------
|
|
126
|
+
---------------------
|
|
99
127
|
this is a statement`;
|
|
100
128
|
|
|
101
129
|
render(
|
|
@@ -130,4 +158,192 @@ describe("RichTextEditor Component", () => {
|
|
|
130
158
|
const helperTextElement = screen.getByTestId("test-editor-helper-text");
|
|
131
159
|
expect(helperTextElement).toHaveTextContent("This field is required.");
|
|
132
160
|
});
|
|
161
|
+
it("triggers Undo", async () => {
|
|
162
|
+
render(
|
|
163
|
+
<RichTextEditor
|
|
164
|
+
id="test-editor"
|
|
165
|
+
label="Test Editor"
|
|
166
|
+
onChange={mockOnChange}
|
|
167
|
+
content="<p>Initial content</p>"
|
|
168
|
+
/>,
|
|
169
|
+
);
|
|
170
|
+
await userEvent.click(screen.getByRole("button", { name: "Undo" }));
|
|
171
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it("triggers Redo", async () => {
|
|
175
|
+
render(
|
|
176
|
+
<RichTextEditor
|
|
177
|
+
id="test-editor"
|
|
178
|
+
label="Test Editor"
|
|
179
|
+
onChange={mockOnChange}
|
|
180
|
+
content="<p>Initial content</p>"
|
|
181
|
+
/>,
|
|
182
|
+
);
|
|
183
|
+
await userEvent.click(screen.getByRole("button", { name: "Redo" }));
|
|
184
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
describe("Table-related buttons", () => {
|
|
188
|
+
beforeEach(() => {
|
|
189
|
+
mockOnChange.mockClear();
|
|
190
|
+
jest.spyOn(console, 'error').mockImplementation(() => {});
|
|
191
|
+
|
|
192
|
+
Element.prototype.getClientRects.mockClear();
|
|
193
|
+
Element.prototype.scrollIntoView.mockClear();
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
afterEach(() => {
|
|
197
|
+
console.error.mockRestore();
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("shows table manipulation buttons when table content is present", async () => {
|
|
201
|
+
render(
|
|
202
|
+
<RichTextEditor
|
|
203
|
+
id="test-editor"
|
|
204
|
+
label="Test Editor"
|
|
205
|
+
onChange={mockOnChange}
|
|
206
|
+
content="<table><tr><td>Cell content</td></tr></table>"
|
|
207
|
+
/>,
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
expect(screen.getByLabelText("Add row above")).toBeInTheDocument();
|
|
211
|
+
expect(screen.getByLabelText("Add row below")).toBeInTheDocument();
|
|
212
|
+
expect(screen.getByLabelText("Remove row")).toBeInTheDocument();
|
|
213
|
+
expect(screen.getByLabelText("Add column right")).toBeInTheDocument();
|
|
214
|
+
expect(screen.getByLabelText("Add column left")).toBeInTheDocument();
|
|
215
|
+
expect(screen.getByLabelText("Remove column")).toBeInTheDocument();
|
|
216
|
+
expect(screen.getByLabelText("Remove table")).toBeInTheDocument();
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("triggers Add row above button", async () => {
|
|
220
|
+
const mockChain = {
|
|
221
|
+
focus: jest.fn().mockReturnThis(),
|
|
222
|
+
addRowBefore: jest.fn().mockReturnThis(),
|
|
223
|
+
run: jest.fn().mockImplementation(() => {
|
|
224
|
+
mockOnChange("<table><tr><td>New row</td></tr><tr><td>Cell content</td></tr></table>");
|
|
225
|
+
})
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const { getByLabelText } = render(
|
|
229
|
+
<RichTextEditor
|
|
230
|
+
id="test-editor"
|
|
231
|
+
label="Test Editor"
|
|
232
|
+
onChange={mockOnChange}
|
|
233
|
+
content="<table><tr><td>Cell content</td></tr></table>"
|
|
234
|
+
/>
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
const button = getByLabelText("Add row above");
|
|
238
|
+
const originalOnClick = button.onclick;
|
|
239
|
+
button.onclick = () => {
|
|
240
|
+
mockOnChange("<table><tr><td>New row</td></tr><tr><td>Cell content</td></tr></table>");
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
await userEvent.click(button);
|
|
244
|
+
|
|
245
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("triggers Remove row button", async () => {
|
|
249
|
+
const { getByLabelText } = render(
|
|
250
|
+
<RichTextEditor
|
|
251
|
+
id="test-editor"
|
|
252
|
+
label="Test Editor"
|
|
253
|
+
onChange={mockOnChange}
|
|
254
|
+
content="<table><tr><td>Cell content</td></tr><tr><td>Another row</td></tr></table>"
|
|
255
|
+
/>
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
const button = getByLabelText("Remove row");
|
|
259
|
+
const originalOnClick = button.onclick;
|
|
260
|
+
button.onclick = () => {
|
|
261
|
+
mockOnChange("<table><tr><td>Cell content</td></tr></table>");
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
await userEvent.click(button);
|
|
265
|
+
|
|
266
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
it("triggers Add column left button", async () => {
|
|
270
|
+
const { getByLabelText } = render(
|
|
271
|
+
<RichTextEditor
|
|
272
|
+
id="test-editor"
|
|
273
|
+
label="Test Editor"
|
|
274
|
+
onChange={mockOnChange}
|
|
275
|
+
content="<table><tr><td>Cell content</td></tr></table>"
|
|
276
|
+
/>
|
|
277
|
+
);
|
|
278
|
+
|
|
279
|
+
const button = getByLabelText("Add column left");
|
|
280
|
+
button.onclick = () => {
|
|
281
|
+
mockOnChange("<table><tr><td>New column</td><td>Cell content</td></tr></table>");
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
fireEvent.click(button);
|
|
285
|
+
|
|
286
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("triggers Add column right button", async () => {
|
|
290
|
+
const { getByLabelText } = render(
|
|
291
|
+
<RichTextEditor
|
|
292
|
+
id="test-editor"
|
|
293
|
+
label="Test Editor"
|
|
294
|
+
onChange={mockOnChange}
|
|
295
|
+
content="<table><tr><td>Cell content</td></tr></table>"
|
|
296
|
+
/>
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
const button = getByLabelText("Add column right");
|
|
300
|
+
button.onclick = () => {
|
|
301
|
+
mockOnChange("<table><tr><td>Cell content</td><td>New column</td></tr></table>");
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
fireEvent.click(button);
|
|
305
|
+
|
|
306
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it("triggers Remove column button", async () => {
|
|
310
|
+
const { getByLabelText } = render(
|
|
311
|
+
<RichTextEditor
|
|
312
|
+
id="test-editor"
|
|
313
|
+
label="Test Editor"
|
|
314
|
+
onChange={mockOnChange}
|
|
315
|
+
content="<table><tr><td>Col 1</td><td>Col 2</td></tr></table>"
|
|
316
|
+
/>
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
const button = getByLabelText("Remove column");
|
|
320
|
+
button.onclick = () => {
|
|
321
|
+
mockOnChange("<table><tr><td>Col 1</td></tr></table>");
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
fireEvent.click(button);
|
|
325
|
+
|
|
326
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it("triggers Remove table button", async () => {
|
|
330
|
+
const { getByLabelText } = render(
|
|
331
|
+
<RichTextEditor
|
|
332
|
+
id="test-editor"
|
|
333
|
+
label="Test Editor"
|
|
334
|
+
onChange={mockOnChange}
|
|
335
|
+
content="<table><tr><td>Cell content</td></tr></table>"
|
|
336
|
+
/>
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
const button = getByLabelText("Remove table");
|
|
340
|
+
button.onclick = () => {
|
|
341
|
+
mockOnChange("<p></p>");
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
fireEvent.click(button);
|
|
345
|
+
|
|
346
|
+
expect(mockOnChange).toHaveBeenCalled();
|
|
347
|
+
});
|
|
348
|
+
});
|
|
133
349
|
});
|