@pie-lib/editable-html 13.1.0-beta.2 → 13.1.0-beta.3
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/package.json +3 -3
- package/src/__tests__/editor-utils.test.js +0 -162
- package/src/__tests__/serialization.test.js +0 -290
- package/src/__tests__/utils.js +0 -36
- package/src/plugins/image/__tests__/component.test.jsx +0 -73
- package/src/plugins/image/__tests__/image-toolbar-logic.test.jsx +0 -90
- package/src/plugins/image/__tests__/image-toolbar.test.jsx +0 -12
- package/src/plugins/image/__tests__/index.test.js +0 -92
- package/src/plugins/image/__tests__/insert-image-handler.test.js +0 -113
- package/src/plugins/image/__tests__/mock-change.js +0 -15
- package/src/plugins/list/__tests__/index.test.js +0 -52
- package/src/plugins/math/__tests__/index.test.jsx +0 -264
- package/src/plugins/media/__tests__/index.test.js +0 -75
- package/src/plugins/respArea/drag-in-the-blank/__tests__/choice.test.js +0 -71
- package/src/plugins/table/__tests__/index.test.jsx +0 -401
- package/src/plugins/table/__tests__/table-toolbar.test.jsx +0 -75
- package/src/plugins/toolbar/__tests__/default-toolbar.test.jsx +0 -123
- package/src/plugins/toolbar/__tests__/editor-and-toolbar.test.jsx +0 -40
- package/src/plugins/toolbar/__tests__/toolbar-buttons.test.jsx +0 -97
- package/src/plugins/toolbar/__tests__/toolbar.test.jsx +0 -112
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pie-lib/editable-html",
|
|
3
|
-
"version": "13.1.0-beta.
|
|
3
|
+
"version": "13.1.0-beta.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
"@mui/icons-material": "^7.3.4",
|
|
17
17
|
"@mui/material": "^7.3.4",
|
|
18
18
|
"@pie-lib/drag": "^4.0.2",
|
|
19
|
-
"@pie-lib/math-input-mathlive": "^1.0.
|
|
19
|
+
"@pie-lib/math-input-mathlive": "^1.0.13",
|
|
20
20
|
"@pie-lib/math-rendering": "^5.0.2",
|
|
21
|
-
"@pie-lib/math-toolbar": "^3.1.0-beta.
|
|
21
|
+
"@pie-lib/math-toolbar": "^3.1.0-beta.9",
|
|
22
22
|
"@pie-lib/render-ui": "^6.1.0",
|
|
23
23
|
"change-case": "^3.0.2",
|
|
24
24
|
"classnames": "^2.2.6",
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
import { buildSizeStyle, valueToSize } from '../editor';
|
|
2
|
-
|
|
3
|
-
describe('Editor Utilities', () => {
|
|
4
|
-
describe('valueToSize', () => {
|
|
5
|
-
it('returns undefined for falsy values', () => {
|
|
6
|
-
expect(valueToSize(null)).toBeUndefined();
|
|
7
|
-
expect(valueToSize(undefined)).toBeUndefined();
|
|
8
|
-
expect(valueToSize('')).toBeUndefined();
|
|
9
|
-
expect(valueToSize(0)).toBeUndefined();
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('converts number to px string', () => {
|
|
13
|
-
expect(valueToSize(100)).toBe('100px');
|
|
14
|
-
expect(valueToSize(50)).toBe('50px');
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it('returns undefined for percentage strings', () => {
|
|
18
|
-
expect(valueToSize('100%')).toBeUndefined();
|
|
19
|
-
expect(valueToSize('50%')).toBeUndefined();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('preserves valid CSS unit strings', () => {
|
|
23
|
-
expect(valueToSize('100px')).toBe('100px');
|
|
24
|
-
expect(valueToSize('10vh')).toBe('10vh');
|
|
25
|
-
expect(valueToSize('50vw')).toBe('50vw');
|
|
26
|
-
expect(valueToSize('9ch')).toBe('9ch');
|
|
27
|
-
expect(valueToSize('2em')).toBe('2em');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('preserves calc() expressions', () => {
|
|
31
|
-
expect(valueToSize('calc(10em + 42px)')).toBe('calc(10em + 42px)');
|
|
32
|
-
expect(valueToSize('calc(100% - 20px)')).toBe('calc(100% - 20px)');
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('converts numeric strings to px', () => {
|
|
36
|
-
expect(valueToSize('100')).toBe('100px');
|
|
37
|
-
expect(valueToSize('50')).toBe('50px');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
it('handles invalid numeric strings', () => {
|
|
41
|
-
const result = valueToSize('invalid');
|
|
42
|
-
expect(isNaN(result)).toBe(true);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
describe('buildSizeStyle', () => {
|
|
47
|
-
it('builds style with numeric width', () => {
|
|
48
|
-
const result = buildSizeStyle({ width: 100 });
|
|
49
|
-
expect(result).toEqual({
|
|
50
|
-
width: '100px',
|
|
51
|
-
minWidth: undefined,
|
|
52
|
-
maxWidth: undefined,
|
|
53
|
-
height: undefined,
|
|
54
|
-
minHeight: undefined,
|
|
55
|
-
maxHeight: undefined,
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it('returns undefined for percentage values', () => {
|
|
60
|
-
const result = buildSizeStyle({ height: '100%', width: '100%' });
|
|
61
|
-
expect(result).toEqual({
|
|
62
|
-
width: undefined,
|
|
63
|
-
height: undefined,
|
|
64
|
-
minWidth: undefined,
|
|
65
|
-
maxWidth: undefined,
|
|
66
|
-
minHeight: undefined,
|
|
67
|
-
maxHeight: undefined,
|
|
68
|
-
});
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('builds style with numeric height', () => {
|
|
72
|
-
const result = buildSizeStyle({ height: 100 });
|
|
73
|
-
expect(result).toEqual({
|
|
74
|
-
width: undefined,
|
|
75
|
-
minWidth: undefined,
|
|
76
|
-
maxWidth: undefined,
|
|
77
|
-
height: '100px',
|
|
78
|
-
minHeight: undefined,
|
|
79
|
-
maxHeight: undefined,
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it('builds style with minHeight', () => {
|
|
84
|
-
const result = buildSizeStyle({ minHeight: 100 });
|
|
85
|
-
expect(result).toEqual({
|
|
86
|
-
width: undefined,
|
|
87
|
-
minWidth: undefined,
|
|
88
|
-
maxWidth: undefined,
|
|
89
|
-
height: undefined,
|
|
90
|
-
minHeight: '100px',
|
|
91
|
-
maxHeight: undefined,
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
it('builds style with maxHeight', () => {
|
|
96
|
-
const result = buildSizeStyle({ maxHeight: 100 });
|
|
97
|
-
expect(result).toEqual({
|
|
98
|
-
width: undefined,
|
|
99
|
-
minWidth: undefined,
|
|
100
|
-
maxWidth: undefined,
|
|
101
|
-
height: undefined,
|
|
102
|
-
minHeight: undefined,
|
|
103
|
-
maxHeight: '100px',
|
|
104
|
-
});
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('builds style with calc() expression', () => {
|
|
108
|
-
const result = buildSizeStyle({ width: 'calc(10em + 42px)' });
|
|
109
|
-
expect(result).toEqual({
|
|
110
|
-
width: 'calc(10em + 42px)',
|
|
111
|
-
minWidth: undefined,
|
|
112
|
-
maxWidth: undefined,
|
|
113
|
-
height: undefined,
|
|
114
|
-
minHeight: undefined,
|
|
115
|
-
maxHeight: undefined,
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('builds style with ch unit', () => {
|
|
120
|
-
const result = buildSizeStyle({ width: '9ch' });
|
|
121
|
-
expect(result).toEqual({
|
|
122
|
-
width: '9ch',
|
|
123
|
-
minWidth: undefined,
|
|
124
|
-
maxWidth: undefined,
|
|
125
|
-
height: undefined,
|
|
126
|
-
minHeight: undefined,
|
|
127
|
-
maxHeight: undefined,
|
|
128
|
-
});
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
it('builds style with no size props', () => {
|
|
132
|
-
const result = buildSizeStyle({});
|
|
133
|
-
expect(result).toEqual({
|
|
134
|
-
width: undefined,
|
|
135
|
-
minWidth: undefined,
|
|
136
|
-
maxWidth: undefined,
|
|
137
|
-
height: undefined,
|
|
138
|
-
minHeight: undefined,
|
|
139
|
-
maxHeight: undefined,
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('builds style with multiple size constraints', () => {
|
|
144
|
-
const result = buildSizeStyle({
|
|
145
|
-
width: 500,
|
|
146
|
-
minWidth: 300,
|
|
147
|
-
maxWidth: 700,
|
|
148
|
-
height: 400,
|
|
149
|
-
minHeight: 200,
|
|
150
|
-
maxHeight: 600,
|
|
151
|
-
});
|
|
152
|
-
expect(result).toEqual({
|
|
153
|
-
width: '500px',
|
|
154
|
-
minWidth: '300px',
|
|
155
|
-
maxWidth: '700px',
|
|
156
|
-
height: '400px',
|
|
157
|
-
minHeight: '200px',
|
|
158
|
-
maxHeight: '600px',
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
});
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
import { htmlToValue, TEXT_RULE } from '../serialization';
|
|
2
|
-
|
|
3
|
-
jest.mock('../plugins/math', () => ({
|
|
4
|
-
serialization: {
|
|
5
|
-
serialize: jest.fn((o, c) => {
|
|
6
|
-
return undefined;
|
|
7
|
-
}),
|
|
8
|
-
deserialize: jest.fn((el, next) => {
|
|
9
|
-
return undefined;
|
|
10
|
-
}),
|
|
11
|
-
},
|
|
12
|
-
}));
|
|
13
|
-
|
|
14
|
-
describe('TEXT_RULE', () => {
|
|
15
|
-
const mkBr = (previousSibling) => {
|
|
16
|
-
return {
|
|
17
|
-
remove: jest.fn(),
|
|
18
|
-
previousSibling,
|
|
19
|
-
replaceWith: (foo) => {
|
|
20
|
-
previousSibling.textContent = previousSibling.textContent.replace(/(<br>)|(<\/br>)/g, foo);
|
|
21
|
-
},
|
|
22
|
-
normalize: jest.fn().mockReturnThis(),
|
|
23
|
-
tagName: 'br',
|
|
24
|
-
};
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const mkTextNode = (textContent = '') => ({
|
|
28
|
-
nodeName: '#text',
|
|
29
|
-
textContent,
|
|
30
|
-
normalize: jest.fn().mockReturnThis(),
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
const mkEl = (querySelectorAllResult) => ({
|
|
34
|
-
querySelectorAll: jest.fn().mockReturnValue(querySelectorAllResult),
|
|
35
|
-
normalize: jest.fn().mockReturnThis(),
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
describe('deserialize', () => {
|
|
39
|
-
it('if no previous text node, no error is thrown', () => {
|
|
40
|
-
const br = mkBr();
|
|
41
|
-
const el = mkEl([br]);
|
|
42
|
-
expect(() => TEXT_RULE.deserialize(el)).not.toThrow();
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
describe('htmlToValue', () => {
|
|
48
|
-
it('converts', () => {
|
|
49
|
-
const expected = {
|
|
50
|
-
object: 'value',
|
|
51
|
-
document: {
|
|
52
|
-
object: 'document',
|
|
53
|
-
data: {},
|
|
54
|
-
nodes: [
|
|
55
|
-
{
|
|
56
|
-
object: 'block',
|
|
57
|
-
type: 'div',
|
|
58
|
-
isVoid: false,
|
|
59
|
-
data: {
|
|
60
|
-
attributes: {},
|
|
61
|
-
},
|
|
62
|
-
nodes: [
|
|
63
|
-
{
|
|
64
|
-
object: 'block',
|
|
65
|
-
type: 'paragraph',
|
|
66
|
-
isVoid: false,
|
|
67
|
-
data: {
|
|
68
|
-
attributes: {},
|
|
69
|
-
},
|
|
70
|
-
nodes: [
|
|
71
|
-
{
|
|
72
|
-
object: 'text',
|
|
73
|
-
leaves: [
|
|
74
|
-
{
|
|
75
|
-
object: 'leaf',
|
|
76
|
-
text: 'foo',
|
|
77
|
-
marks: [],
|
|
78
|
-
},
|
|
79
|
-
],
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
object: 'inline',
|
|
83
|
-
type: 'image',
|
|
84
|
-
isVoid: true,
|
|
85
|
-
data: {
|
|
86
|
-
src: 'blah.jpg',
|
|
87
|
-
width: null,
|
|
88
|
-
height: null,
|
|
89
|
-
margin: '',
|
|
90
|
-
justifyContent: '',
|
|
91
|
-
alignment: null,
|
|
92
|
-
alt: null,
|
|
93
|
-
},
|
|
94
|
-
nodes: [
|
|
95
|
-
{
|
|
96
|
-
object: 'text',
|
|
97
|
-
leaves: [
|
|
98
|
-
{
|
|
99
|
-
object: 'leaf',
|
|
100
|
-
text: '',
|
|
101
|
-
marks: [],
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
object: 'text',
|
|
109
|
-
leaves: [
|
|
110
|
-
{
|
|
111
|
-
object: 'leaf',
|
|
112
|
-
text: 'bar',
|
|
113
|
-
marks: [],
|
|
114
|
-
},
|
|
115
|
-
],
|
|
116
|
-
},
|
|
117
|
-
],
|
|
118
|
-
},
|
|
119
|
-
],
|
|
120
|
-
},
|
|
121
|
-
],
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
const html = `<div><p>foo<img src="blah.jpg"/>bar</p></div>`;
|
|
125
|
-
const v = htmlToValue(html);
|
|
126
|
-
|
|
127
|
-
expect(v.toJSON()).toEqual(expected);
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('does not break', () => {
|
|
131
|
-
/*
|
|
132
|
-
More than 12 iterations of the same kind would previously break the input. Here we have 16 text nodes, and now it works.
|
|
133
|
-
*/
|
|
134
|
-
const expected = {
|
|
135
|
-
object: 'value',
|
|
136
|
-
document: {
|
|
137
|
-
object: 'document',
|
|
138
|
-
data: {},
|
|
139
|
-
nodes: [
|
|
140
|
-
{
|
|
141
|
-
object: 'block',
|
|
142
|
-
type: 'div',
|
|
143
|
-
isVoid: false,
|
|
144
|
-
data: { attributes: {} },
|
|
145
|
-
nodes: [
|
|
146
|
-
{
|
|
147
|
-
object: 'text',
|
|
148
|
-
leaves: [
|
|
149
|
-
{
|
|
150
|
-
object: 'leaf',
|
|
151
|
-
text: 'Foo ',
|
|
152
|
-
marks: [],
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
object: 'leaf',
|
|
156
|
-
text: 'x',
|
|
157
|
-
marks: [
|
|
158
|
-
{
|
|
159
|
-
object: 'mark',
|
|
160
|
-
type: 'italic',
|
|
161
|
-
data: {},
|
|
162
|
-
},
|
|
163
|
-
],
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
object: 'leaf',
|
|
167
|
-
text: ' bar ',
|
|
168
|
-
marks: [],
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
object: 'leaf',
|
|
172
|
-
text: 'x',
|
|
173
|
-
marks: [
|
|
174
|
-
{
|
|
175
|
-
object: 'mark',
|
|
176
|
-
type: 'italic',
|
|
177
|
-
data: {},
|
|
178
|
-
},
|
|
179
|
-
],
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
object: 'leaf',
|
|
183
|
-
text: ' Foo ',
|
|
184
|
-
marks: [],
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
object: 'leaf',
|
|
188
|
-
text: 'x',
|
|
189
|
-
marks: [
|
|
190
|
-
{
|
|
191
|
-
object: 'mark',
|
|
192
|
-
type: 'italic',
|
|
193
|
-
data: {},
|
|
194
|
-
},
|
|
195
|
-
],
|
|
196
|
-
},
|
|
197
|
-
{
|
|
198
|
-
object: 'leaf',
|
|
199
|
-
text: ' bar ',
|
|
200
|
-
marks: [],
|
|
201
|
-
},
|
|
202
|
-
{
|
|
203
|
-
object: 'leaf',
|
|
204
|
-
text: 'x',
|
|
205
|
-
marks: [
|
|
206
|
-
{
|
|
207
|
-
object: 'mark',
|
|
208
|
-
type: 'italic',
|
|
209
|
-
data: {},
|
|
210
|
-
},
|
|
211
|
-
],
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
object: 'leaf',
|
|
215
|
-
text: ' Foo ',
|
|
216
|
-
marks: [],
|
|
217
|
-
},
|
|
218
|
-
{
|
|
219
|
-
object: 'leaf',
|
|
220
|
-
text: 'x',
|
|
221
|
-
marks: [
|
|
222
|
-
{
|
|
223
|
-
object: 'mark',
|
|
224
|
-
type: 'italic',
|
|
225
|
-
data: {},
|
|
226
|
-
},
|
|
227
|
-
],
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
object: 'leaf',
|
|
231
|
-
text: ' bar ',
|
|
232
|
-
marks: [],
|
|
233
|
-
},
|
|
234
|
-
{
|
|
235
|
-
object: 'leaf',
|
|
236
|
-
text: 'x',
|
|
237
|
-
marks: [
|
|
238
|
-
{
|
|
239
|
-
object: 'mark',
|
|
240
|
-
type: 'italic',
|
|
241
|
-
data: {},
|
|
242
|
-
},
|
|
243
|
-
],
|
|
244
|
-
},
|
|
245
|
-
{
|
|
246
|
-
object: 'leaf',
|
|
247
|
-
text: ' Foo ',
|
|
248
|
-
marks: [],
|
|
249
|
-
},
|
|
250
|
-
{
|
|
251
|
-
object: 'leaf',
|
|
252
|
-
text: 'x',
|
|
253
|
-
marks: [
|
|
254
|
-
{
|
|
255
|
-
object: 'mark',
|
|
256
|
-
type: 'italic',
|
|
257
|
-
data: {},
|
|
258
|
-
},
|
|
259
|
-
],
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
object: 'leaf',
|
|
263
|
-
text: ' bar ',
|
|
264
|
-
marks: [],
|
|
265
|
-
},
|
|
266
|
-
{
|
|
267
|
-
object: 'leaf',
|
|
268
|
-
text: 'x',
|
|
269
|
-
marks: [
|
|
270
|
-
{
|
|
271
|
-
object: 'mark',
|
|
272
|
-
type: 'italic',
|
|
273
|
-
data: {},
|
|
274
|
-
},
|
|
275
|
-
],
|
|
276
|
-
},
|
|
277
|
-
],
|
|
278
|
-
},
|
|
279
|
-
],
|
|
280
|
-
},
|
|
281
|
-
],
|
|
282
|
-
},
|
|
283
|
-
};
|
|
284
|
-
const html =
|
|
285
|
-
'<div>Foo <em>x</em> bar <em>x</em> Foo <em>x</em> bar <em>x</em> Foo <em>x</em> bar <em>x</em> Foo <em>x</em> bar <em>x</em></div>';
|
|
286
|
-
const v = htmlToValue(html);
|
|
287
|
-
|
|
288
|
-
expect(v.toJSON()).toEqual(expected);
|
|
289
|
-
});
|
|
290
|
-
});
|
package/src/__tests__/utils.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
export function classObject() {
|
|
4
|
-
const out = {};
|
|
5
|
-
for (var a in arguments) {
|
|
6
|
-
const value = arguments[a];
|
|
7
|
-
out[value] = value;
|
|
8
|
-
}
|
|
9
|
-
return out;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function mockComponents() {
|
|
13
|
-
const out = {};
|
|
14
|
-
for (var a in arguments) {
|
|
15
|
-
const value = arguments[a];
|
|
16
|
-
out[value] = class extends React.Component {
|
|
17
|
-
render() {
|
|
18
|
-
return <div data-mock-component="true">{value}</div>;
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
return out;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function mockIconButton() {
|
|
26
|
-
jest.mock('@mui/material/IconButton', () => {
|
|
27
|
-
return (props) => <div className={props.className} style={props.style} ariaLabel={props['aria-label']} />;
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
export function mockMathInput() {
|
|
31
|
-
jest.mock('@pie-lib/math-input-mathlive', () => ({
|
|
32
|
-
addBrackets: jest.fn((s) => s),
|
|
33
|
-
removeBrackets: jest.fn((s) => s),
|
|
34
|
-
...mockComponents('Keypad', 'MathQuillInput', 'EditableMathInput', 'HorizontalKeypad'),
|
|
35
|
-
}));
|
|
36
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
import { Block, Data } from 'slate';
|
|
4
|
-
import { Component } from '../component';
|
|
5
|
-
|
|
6
|
-
describe('Image Component', () => {
|
|
7
|
-
const createImageNode = (dataProps = {}) => {
|
|
8
|
-
return Block.fromJSON({
|
|
9
|
-
type: 'image',
|
|
10
|
-
data: Data.create({
|
|
11
|
-
width: 50,
|
|
12
|
-
height: 50,
|
|
13
|
-
src: 'test-image.jpg',
|
|
14
|
-
...dataProps,
|
|
15
|
-
}),
|
|
16
|
-
});
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const createMockEditor = () => ({
|
|
20
|
-
value: {},
|
|
21
|
-
change: jest.fn(),
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const defaultClasses = {
|
|
25
|
-
active: 'active',
|
|
26
|
-
loading: 'loading',
|
|
27
|
-
pendingDelete: 'pendingDelete',
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const defaultProps = {
|
|
31
|
-
node: createImageNode(),
|
|
32
|
-
editor: createMockEditor(),
|
|
33
|
-
classes: defaultClasses,
|
|
34
|
-
onDelete: jest.fn(),
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
it('renders correctly with default props', () => {
|
|
38
|
-
const { container } = render(<Component {...defaultProps} />);
|
|
39
|
-
expect(container.firstChild).toBeInTheDocument();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('renders image with correct dimensions', () => {
|
|
43
|
-
const { container } = render(<Component {...defaultProps} />);
|
|
44
|
-
const img = container.querySelector('img');
|
|
45
|
-
expect(img).toBeInTheDocument();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('renders with custom width and height', () => {
|
|
49
|
-
const node = createImageNode({ width: 100, height: 200 });
|
|
50
|
-
const { container } = render(<Component {...defaultProps} node={node} />);
|
|
51
|
-
const img = container.querySelector('img');
|
|
52
|
-
expect(img).toBeInTheDocument();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('renders with loading class when loading', () => {
|
|
56
|
-
const node = createImageNode({ loading: true });
|
|
57
|
-
const { container } = render(<Component {...defaultProps} node={node} />);
|
|
58
|
-
expect(container.firstChild).toBeInTheDocument();
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('renders with active class when active', () => {
|
|
62
|
-
const node = createImageNode({ active: true });
|
|
63
|
-
const { container } = render(<Component {...defaultProps} node={node} />);
|
|
64
|
-
expect(container.firstChild).toBeInTheDocument();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('handles image with source', () => {
|
|
68
|
-
const node = createImageNode({ src: 'test-image.jpg' });
|
|
69
|
-
const { container } = render(<Component {...defaultProps} node={node} />);
|
|
70
|
-
const img = container.querySelector('img');
|
|
71
|
-
expect(img).toHaveAttribute('src', 'test-image.jpg');
|
|
72
|
-
});
|
|
73
|
-
});
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { render, screen } from '@testing-library/react';
|
|
2
|
-
import userEvent from '@testing-library/user-event';
|
|
3
|
-
import { ImageToolbar } from '../image-toolbar';
|
|
4
|
-
import React from 'react';
|
|
5
|
-
|
|
6
|
-
// Mock the alt-dialog component to avoid complex modal rendering in tests
|
|
7
|
-
jest.mock('../alt-dialog', () => {
|
|
8
|
-
return function AltDialog({ alt, onDone }) {
|
|
9
|
-
return (
|
|
10
|
-
<div data-testid="alt-dialog">
|
|
11
|
-
<input data-testid="alt-input" defaultValue={alt} onChange={(e) => onDone(e.target.value)} />
|
|
12
|
-
</div>
|
|
13
|
-
);
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
describe('ImageToolbar', () => {
|
|
18
|
-
let onChange;
|
|
19
|
-
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
onChange = jest.fn();
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
const renderComponent = (extras = {}) => {
|
|
25
|
-
const props = {
|
|
26
|
-
onChange,
|
|
27
|
-
imageLoaded: true,
|
|
28
|
-
...extras,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
return render(<ImageToolbar {...props} />);
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
describe('rendering', () => {
|
|
35
|
-
it('renders alignment buttons', () => {
|
|
36
|
-
renderComponent();
|
|
37
|
-
expect(screen.getByText('left')).toBeInTheDocument();
|
|
38
|
-
expect(screen.getByText('center')).toBeInTheDocument();
|
|
39
|
-
expect(screen.getByText('right')).toBeInTheDocument();
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('renders alt text button', () => {
|
|
43
|
-
renderComponent();
|
|
44
|
-
expect(screen.getByText('Alt text')).toBeInTheDocument();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('does not render alignment buttons when disabled', () => {
|
|
48
|
-
renderComponent({ disableImageAlignmentButtons: true });
|
|
49
|
-
expect(screen.queryByText('left')).not.toBeInTheDocument();
|
|
50
|
-
expect(screen.queryByText('center')).not.toBeInTheDocument();
|
|
51
|
-
expect(screen.queryByText('right')).not.toBeInTheDocument();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('shows active state for selected alignment', () => {
|
|
55
|
-
const { container } = renderComponent({ alignment: 'center' });
|
|
56
|
-
// The MarkButton component uses aria-pressed for active state
|
|
57
|
-
const centerButton = screen.getByText('center').closest('button');
|
|
58
|
-
expect(centerButton).toHaveAttribute('aria-pressed', 'true');
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
describe('user interactions', () => {
|
|
63
|
-
it('calls onChange with alignment when left is clicked', async () => {
|
|
64
|
-
const user = userEvent.setup();
|
|
65
|
-
renderComponent();
|
|
66
|
-
|
|
67
|
-
await user.click(screen.getByText('left'));
|
|
68
|
-
|
|
69
|
-
expect(onChange).toHaveBeenCalledWith({ alignment: 'left' });
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('calls onChange with alignment when center is clicked', async () => {
|
|
73
|
-
const user = userEvent.setup();
|
|
74
|
-
renderComponent();
|
|
75
|
-
|
|
76
|
-
await user.click(screen.getByText('center'));
|
|
77
|
-
|
|
78
|
-
expect(onChange).toHaveBeenCalledWith({ alignment: 'center' });
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('calls onChange with alignment when right is clicked', async () => {
|
|
82
|
-
const user = userEvent.setup();
|
|
83
|
-
renderComponent();
|
|
84
|
-
|
|
85
|
-
await user.click(screen.getByText('right'));
|
|
86
|
-
|
|
87
|
-
expect(onChange).toHaveBeenCalledWith({ alignment: 'right' });
|
|
88
|
-
});
|
|
89
|
-
});
|
|
90
|
-
});
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import Toolbar from '../image-toolbar';
|
|
3
|
-
import { render } from '@testing-library/react';
|
|
4
|
-
|
|
5
|
-
it('renders image toolbar', () => {
|
|
6
|
-
const classes = { holder: 'holder' };
|
|
7
|
-
|
|
8
|
-
const { container } = render(<Toolbar percent={50} classes={classes} onChange={jest.fn()} />);
|
|
9
|
-
|
|
10
|
-
// Verify the toolbar is rendered
|
|
11
|
-
expect(container.firstChild).toBeInTheDocument();
|
|
12
|
-
});
|