@madie/madie-design-system 1.2.77 → 1.2.78
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 +88 -65
- package/dist/browser.js +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.js +1 -1
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/test/components/MadieDeleteDialog.test.js +1 -1
- package/test/components/RichTextEditor.test.js +257 -37
package/package.json
CHANGED
|
@@ -132,7 +132,7 @@ describe("MadieDeleteDialog", () => {
|
|
|
132
132
|
queryByText("This Action cannot be undone.")
|
|
133
133
|
).not.toBeInTheDocument();
|
|
134
134
|
expect(
|
|
135
|
-
queryByText("<p><strong>test &</strong></p><p>test2</p>")
|
|
135
|
+
queryByText("<p><strong>test &</strong></p><p>test2</p>")
|
|
136
136
|
).not.toBeInTheDocument();
|
|
137
137
|
expect(getByText("test &")).toBeInTheDocument();
|
|
138
138
|
expect(getByText("test2")).toBeInTheDocument();
|
|
@@ -1,34 +1,42 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
render,
|
|
4
|
+
screen,
|
|
5
|
+
fireEvent,
|
|
6
|
+
waitFor,
|
|
7
|
+
act,
|
|
8
|
+
} from "@testing-library/react";
|
|
3
9
|
import userEvent from "@testing-library/user-event";
|
|
4
|
-
import RichTextEditor from "../../components/RichTextEditor/index";
|
|
10
|
+
import RichTextEditor, { MenuBar } from "../../components/RichTextEditor/index";
|
|
5
11
|
import DOMPurify from "dompurify";
|
|
6
12
|
|
|
7
13
|
beforeAll(() => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
14
|
+
Element.prototype.getClientRects = jest.fn(() => [
|
|
15
|
+
{
|
|
16
|
+
top: 0,
|
|
17
|
+
left: 0,
|
|
18
|
+
bottom: 0,
|
|
19
|
+
right: 0,
|
|
20
|
+
width: 0,
|
|
21
|
+
height: 0,
|
|
22
|
+
},
|
|
23
|
+
]);
|
|
24
|
+
|
|
25
|
+
Element.prototype.scrollIntoView = jest.fn();
|
|
26
|
+
|
|
27
|
+
window.getSelection = jest.fn(() => ({
|
|
28
|
+
removeAllRanges: jest.fn(),
|
|
29
|
+
addRange: jest.fn(),
|
|
30
|
+
}));
|
|
31
|
+
|
|
32
|
+
Element.prototype.getBoundingClientRect = jest.fn(() => ({
|
|
33
|
+
top: 0,
|
|
34
|
+
left: 0,
|
|
35
|
+
bottom: 0,
|
|
36
|
+
right: 0,
|
|
37
|
+
width: 0,
|
|
38
|
+
height: 0,
|
|
39
|
+
}));
|
|
32
40
|
});
|
|
33
41
|
|
|
34
42
|
describe("RichTextEditor Component", () => {
|
|
@@ -77,6 +85,40 @@ describe("RichTextEditor Component", () => {
|
|
|
77
85
|
});
|
|
78
86
|
});
|
|
79
87
|
|
|
88
|
+
it("calls renders withs style", async () => {
|
|
89
|
+
render(
|
|
90
|
+
<RichTextEditor
|
|
91
|
+
id="test-editor"
|
|
92
|
+
label="Description"
|
|
93
|
+
content="Initial Content"
|
|
94
|
+
onChange={mockOnChange}
|
|
95
|
+
disabled={false}
|
|
96
|
+
/>
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
// Simulate content change
|
|
100
|
+
const label = screen.getByTestId("test-editor-label");
|
|
101
|
+
expect(label.className).toMatch(/Mui/);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("calls renders withs style in readOnly", async () => {
|
|
105
|
+
render(
|
|
106
|
+
<RichTextEditor
|
|
107
|
+
readOnly
|
|
108
|
+
id="test-editor"
|
|
109
|
+
label="Description"
|
|
110
|
+
content="Initial Content"
|
|
111
|
+
onChange={mockOnChange}
|
|
112
|
+
disabled={false}
|
|
113
|
+
/>
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
// Simulate content change
|
|
117
|
+
const label = screen.getByTestId("test-editor-label");
|
|
118
|
+
expect(label.className).toMatch(/Mui/);
|
|
119
|
+
expect(label).toHaveTextContent("Description");
|
|
120
|
+
});
|
|
121
|
+
|
|
80
122
|
it("renders sanitized content within editor when disabled is true", () => {
|
|
81
123
|
render(
|
|
82
124
|
<RichTextEditor
|
|
@@ -160,6 +202,61 @@ describe("RichTextEditor Component", () => {
|
|
|
160
202
|
const helperTextElement = screen.getByTestId("test-editor-helper-text");
|
|
161
203
|
expect(helperTextElement).toHaveTextContent("This field is required.");
|
|
162
204
|
});
|
|
205
|
+
|
|
206
|
+
it("displays no helper text", () => {
|
|
207
|
+
render(
|
|
208
|
+
<RichTextEditor
|
|
209
|
+
id="test-editor"
|
|
210
|
+
label="Test Label"
|
|
211
|
+
content={null}
|
|
212
|
+
helperText={null}
|
|
213
|
+
required={true}
|
|
214
|
+
error={true}
|
|
215
|
+
onChange={mockOnChange}
|
|
216
|
+
/>
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
expect(
|
|
220
|
+
screen.queryByTestId("test-editor-helper-text")
|
|
221
|
+
).not.toBeInTheDocument();
|
|
222
|
+
});
|
|
223
|
+
it("verifiably triggers content", () => {
|
|
224
|
+
render(
|
|
225
|
+
<RichTextEditor
|
|
226
|
+
id="test-editor"
|
|
227
|
+
label="Label"
|
|
228
|
+
content="<p>Hello world</p>"
|
|
229
|
+
helperText="Help"
|
|
230
|
+
error={false}
|
|
231
|
+
onChange={mockOnChange}
|
|
232
|
+
/>
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
const editor = screen.getByTestId(
|
|
236
|
+
"test-editor-rich-text-editor-content"
|
|
237
|
+
);
|
|
238
|
+
expect(editor.innerHTML).toContain("Hello world");
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("updates content without rerendering", () => {
|
|
242
|
+
render(
|
|
243
|
+
<RichTextEditor
|
|
244
|
+
id="test-editor"
|
|
245
|
+
label="Label"
|
|
246
|
+
content="<p>Initial</p>"
|
|
247
|
+
helperText="Help"
|
|
248
|
+
error={false}
|
|
249
|
+
onChange={mockOnChange}
|
|
250
|
+
/>
|
|
251
|
+
);
|
|
252
|
+
|
|
253
|
+
act(() => {
|
|
254
|
+
mockOnChange("<p>Updated</p>");
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
expect(mockOnChange).toHaveBeenCalledWith("<p>Updated</p>");
|
|
258
|
+
});
|
|
259
|
+
|
|
163
260
|
it("triggers Undo", async () => {
|
|
164
261
|
render(
|
|
165
262
|
<RichTextEditor
|
|
@@ -167,7 +264,7 @@ describe("RichTextEditor Component", () => {
|
|
|
167
264
|
label="Test Editor"
|
|
168
265
|
onChange={mockOnChange}
|
|
169
266
|
content="<p>Initial content</p>"
|
|
170
|
-
|
|
267
|
+
/>
|
|
171
268
|
);
|
|
172
269
|
await userEvent.click(screen.getByRole("button", { name: "Undo" }));
|
|
173
270
|
expect(mockOnChange).toHaveBeenCalled();
|
|
@@ -180,7 +277,7 @@ describe("RichTextEditor Component", () => {
|
|
|
180
277
|
label="Test Editor"
|
|
181
278
|
onChange={mockOnChange}
|
|
182
279
|
content="<p>Initial content</p>"
|
|
183
|
-
|
|
280
|
+
/>
|
|
184
281
|
);
|
|
185
282
|
await userEvent.click(screen.getByRole("button", { name: "Redo" }));
|
|
186
283
|
expect(mockOnChange).toHaveBeenCalled();
|
|
@@ -189,7 +286,7 @@ describe("RichTextEditor Component", () => {
|
|
|
189
286
|
describe("Table-related buttons", () => {
|
|
190
287
|
beforeEach(() => {
|
|
191
288
|
mockOnChange.mockClear();
|
|
192
|
-
jest.spyOn(console,
|
|
289
|
+
jest.spyOn(console, "error").mockImplementation(() => {});
|
|
193
290
|
|
|
194
291
|
Element.prototype.getClientRects.mockClear();
|
|
195
292
|
Element.prototype.scrollIntoView.mockClear();
|
|
@@ -206,14 +303,18 @@ describe("RichTextEditor Component", () => {
|
|
|
206
303
|
label="Test Editor"
|
|
207
304
|
onChange={mockOnChange}
|
|
208
305
|
content="<table><tr><td>Cell content</td></tr></table>"
|
|
209
|
-
|
|
306
|
+
/>
|
|
210
307
|
);
|
|
211
308
|
|
|
212
309
|
expect(screen.getByLabelText("Add row above")).toBeInTheDocument();
|
|
213
310
|
expect(screen.getByLabelText("Add row below")).toBeInTheDocument();
|
|
214
311
|
expect(screen.getByLabelText("Remove row")).toBeInTheDocument();
|
|
215
|
-
expect(
|
|
216
|
-
|
|
312
|
+
expect(
|
|
313
|
+
screen.getByLabelText("Add column right")
|
|
314
|
+
).toBeInTheDocument();
|
|
315
|
+
expect(
|
|
316
|
+
screen.getByLabelText("Add column left")
|
|
317
|
+
).toBeInTheDocument();
|
|
217
318
|
expect(screen.getByLabelText("Remove column")).toBeInTheDocument();
|
|
218
319
|
expect(screen.getByLabelText("Remove table")).toBeInTheDocument();
|
|
219
320
|
});
|
|
@@ -223,8 +324,10 @@ describe("RichTextEditor Component", () => {
|
|
|
223
324
|
focus: jest.fn().mockReturnThis(),
|
|
224
325
|
addRowBefore: jest.fn().mockReturnThis(),
|
|
225
326
|
run: jest.fn().mockImplementation(() => {
|
|
226
|
-
mockOnChange(
|
|
227
|
-
|
|
327
|
+
mockOnChange(
|
|
328
|
+
"<table><tr><td>New row</td></tr><tr><td>Cell content</td></tr></table>"
|
|
329
|
+
);
|
|
330
|
+
}),
|
|
228
331
|
};
|
|
229
332
|
|
|
230
333
|
const { getByLabelText } = render(
|
|
@@ -239,7 +342,9 @@ describe("RichTextEditor Component", () => {
|
|
|
239
342
|
const button = getByLabelText("Add row above");
|
|
240
343
|
const originalOnClick = button.onclick;
|
|
241
344
|
button.onclick = () => {
|
|
242
|
-
mockOnChange(
|
|
345
|
+
mockOnChange(
|
|
346
|
+
"<table><tr><td>New row</td></tr><tr><td>Cell content</td></tr></table>"
|
|
347
|
+
);
|
|
243
348
|
};
|
|
244
349
|
|
|
245
350
|
await userEvent.click(button);
|
|
@@ -280,7 +385,9 @@ describe("RichTextEditor Component", () => {
|
|
|
280
385
|
|
|
281
386
|
const button = getByLabelText("Add column left");
|
|
282
387
|
button.onclick = () => {
|
|
283
|
-
mockOnChange(
|
|
388
|
+
mockOnChange(
|
|
389
|
+
"<table><tr><td>New column</td><td>Cell content</td></tr></table>"
|
|
390
|
+
);
|
|
284
391
|
};
|
|
285
392
|
|
|
286
393
|
fireEvent.click(button);
|
|
@@ -300,7 +407,9 @@ describe("RichTextEditor Component", () => {
|
|
|
300
407
|
|
|
301
408
|
const button = getByLabelText("Add column right");
|
|
302
409
|
button.onclick = () => {
|
|
303
|
-
mockOnChange(
|
|
410
|
+
mockOnChange(
|
|
411
|
+
"<table><tr><td>Cell content</td><td>New column</td></tr></table>"
|
|
412
|
+
);
|
|
304
413
|
};
|
|
305
414
|
|
|
306
415
|
fireEvent.click(button);
|
|
@@ -335,6 +444,10 @@ describe("RichTextEditor Component", () => {
|
|
|
335
444
|
label="Test Editor"
|
|
336
445
|
onChange={mockOnChange}
|
|
337
446
|
content="<table><tr><td>Cell content</td></tr></table>"
|
|
447
|
+
helperText={undefined}
|
|
448
|
+
sx={{
|
|
449
|
+
color: "red",
|
|
450
|
+
}}
|
|
338
451
|
/>
|
|
339
452
|
);
|
|
340
453
|
|
|
@@ -347,5 +460,112 @@ describe("RichTextEditor Component", () => {
|
|
|
347
460
|
|
|
348
461
|
expect(mockOnChange).toHaveBeenCalled();
|
|
349
462
|
});
|
|
463
|
+
|
|
464
|
+
it("renders helper text", async () => {
|
|
465
|
+
render(
|
|
466
|
+
<RichTextEditor
|
|
467
|
+
id="test-editor"
|
|
468
|
+
label="Test Editor"
|
|
469
|
+
onChange={mockOnChange}
|
|
470
|
+
content="<table><tr><td>Cell content</td></tr></table>"
|
|
471
|
+
helperText="This is helper text"
|
|
472
|
+
/>
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
const helperText = screen.getByText("This is helper text");
|
|
476
|
+
expect(helperText).toBeInTheDocument();
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
it("renders tooltips and buttons", () => {
|
|
480
|
+
render(
|
|
481
|
+
<RichTextEditor
|
|
482
|
+
id="test-editor"
|
|
483
|
+
label="Test Editor"
|
|
484
|
+
onChange={mockOnChange}
|
|
485
|
+
content="<table><tr><td>Cell content</td></tr></table>"
|
|
486
|
+
helperText="This is helper text"
|
|
487
|
+
/>
|
|
488
|
+
);
|
|
489
|
+
//undo
|
|
490
|
+
const undoTooltip = screen.getByTestId("test-editor-undo-tooltip");
|
|
491
|
+
userEvent.hover(undoTooltip);
|
|
492
|
+
expect(undoTooltip).toBeInTheDocument();
|
|
493
|
+
//redo
|
|
494
|
+
const redoTooltip = screen.getByTestId("test-editor-redo-tooltip");
|
|
495
|
+
expect(redoTooltip).toBeInTheDocument();
|
|
496
|
+
//bold
|
|
497
|
+
const boldTooltip = screen.getByTestId("test-editor-bold-tooltip");
|
|
498
|
+
expect(boldTooltip).toBeInTheDocument();
|
|
499
|
+
//italic
|
|
500
|
+
const italicTooltip = screen.getByTestId(
|
|
501
|
+
"test-editor-italic-tooltip"
|
|
502
|
+
);
|
|
503
|
+
expect(italicTooltip).toBeInTheDocument();
|
|
504
|
+
//underline
|
|
505
|
+
const underlineTooltip = screen.getByTestId(
|
|
506
|
+
"test-editor-underline-tooltip"
|
|
507
|
+
);
|
|
508
|
+
expect(underlineTooltip).toBeInTheDocument();
|
|
509
|
+
//strikethrough
|
|
510
|
+
const strikethroughTooltip = screen.getByTestId(
|
|
511
|
+
"test-editor-strikethrough-tooltip"
|
|
512
|
+
);
|
|
513
|
+
expect(strikethroughTooltip).toBeInTheDocument();
|
|
514
|
+
//ordered list
|
|
515
|
+
const orderedListTooltip = screen.getByTestId(
|
|
516
|
+
"test-editor-orderedlist-tooltip"
|
|
517
|
+
);
|
|
518
|
+
expect(orderedListTooltip).toBeInTheDocument();
|
|
519
|
+
//bulleted list
|
|
520
|
+
const bulletedListTooltip = screen.getByTestId(
|
|
521
|
+
"test-editor-bulletedlist-tooltip"
|
|
522
|
+
);
|
|
523
|
+
expect(bulletedListTooltip).toBeInTheDocument();
|
|
524
|
+
//table
|
|
525
|
+
const tableTooltip = screen.getByTestId(
|
|
526
|
+
"test-editor-table-tooltip"
|
|
527
|
+
);
|
|
528
|
+
expect(tableTooltip).toBeInTheDocument();
|
|
529
|
+
//add column right
|
|
530
|
+
const addColumnRightTooltip = screen.getByTestId(
|
|
531
|
+
"test-editor-add-column-right-tooltip"
|
|
532
|
+
);
|
|
533
|
+
expect(addColumnRightTooltip).toBeInTheDocument();
|
|
534
|
+
//add column left
|
|
535
|
+
const addColumnLeftTooltip = screen.getByTestId(
|
|
536
|
+
"test-editor-add-column-left-tooltip"
|
|
537
|
+
);
|
|
538
|
+
expect(addColumnLeftTooltip).toBeInTheDocument();
|
|
539
|
+
//remove column
|
|
540
|
+
const removeColumnTooltip = screen.getByTestId(
|
|
541
|
+
"test-editor-remove-column-tooltip"
|
|
542
|
+
);
|
|
543
|
+
expect(removeColumnTooltip).toBeInTheDocument();
|
|
544
|
+
//remove table
|
|
545
|
+
const removeTableTooltip = screen.getByTestId(
|
|
546
|
+
"test-editor-remove-table-tooltip"
|
|
547
|
+
);
|
|
548
|
+
expect(removeTableTooltip).toBeInTheDocument();
|
|
549
|
+
//add row above
|
|
550
|
+
const addRowAboveTooltip = screen.getByTestId(
|
|
551
|
+
"test-editor-add-row-above-tooltip"
|
|
552
|
+
);
|
|
553
|
+
expect(addRowAboveTooltip).toBeInTheDocument();
|
|
554
|
+
//add row below
|
|
555
|
+
const addRowBelowTooltip = screen.getByTestId(
|
|
556
|
+
"test-editor-add-row-below-tooltip"
|
|
557
|
+
);
|
|
558
|
+
expect(addRowBelowTooltip).toBeInTheDocument();
|
|
559
|
+
//remove row
|
|
560
|
+
const removeRowTooltip = screen.getByTestId(
|
|
561
|
+
"test-editor-remove-row-tooltip"
|
|
562
|
+
);
|
|
563
|
+
expect(removeRowTooltip).toBeInTheDocument();
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
it("renders no menu bar", async () => {
|
|
567
|
+
const { container } = render(<MenuBar />);
|
|
568
|
+
expect(container).toBeEmptyDOMElement();
|
|
569
|
+
});
|
|
350
570
|
});
|
|
351
571
|
});
|