@atlaskit/editor-plugin-table 0.0.6 → 0.0.8

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.
Files changed (90) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/plugins/table/event-handlers.js +7 -6
  3. package/dist/cjs/plugins/table/nodeviews/table.js +4 -2
  4. package/dist/cjs/plugins/table/nodeviews/tableCell.js +4 -4
  5. package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
  6. package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
  7. package/dist/cjs/plugins/table/toolbar.js +0 -1
  8. package/dist/cjs/plugins/table/ui/TableFloatingControls/CornerControls/index.js +23 -10
  9. package/dist/cjs/plugins/table/ui/TableFloatingControls/RowControls/index.js +23 -10
  10. package/dist/cjs/plugins/table/ui/TableFloatingControls/index.js +4 -4
  11. package/dist/cjs/plugins/table/utils/column-controls.js +1 -1
  12. package/dist/cjs/version.json +1 -1
  13. package/dist/es2019/plugins/table/event-handlers.js +8 -7
  14. package/dist/es2019/plugins/table/nodeviews/table.js +4 -2
  15. package/dist/es2019/plugins/table/nodeviews/tableCell.js +3 -4
  16. package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
  17. package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
  18. package/dist/es2019/plugins/table/toolbar.js +1 -2
  19. package/dist/es2019/plugins/table/ui/TableFloatingControls/CornerControls/index.js +18 -3
  20. package/dist/es2019/plugins/table/ui/TableFloatingControls/RowControls/index.js +18 -3
  21. package/dist/es2019/plugins/table/ui/TableFloatingControls/index.js +2 -2
  22. package/dist/es2019/plugins/table/utils/column-controls.js +1 -1
  23. package/dist/es2019/version.json +1 -1
  24. package/dist/esm/plugins/table/event-handlers.js +8 -7
  25. package/dist/esm/plugins/table/nodeviews/table.js +4 -2
  26. package/dist/esm/plugins/table/nodeviews/tableCell.js +3 -4
  27. package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
  28. package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
  29. package/dist/esm/plugins/table/toolbar.js +1 -2
  30. package/dist/esm/plugins/table/ui/TableFloatingControls/CornerControls/index.js +19 -9
  31. package/dist/esm/plugins/table/ui/TableFloatingControls/RowControls/index.js +19 -9
  32. package/dist/esm/plugins/table/ui/TableFloatingControls/index.js +2 -2
  33. package/dist/esm/plugins/table/utils/column-controls.js +1 -1
  34. package/dist/esm/version.json +1 -1
  35. package/dist/types/plugins/table/nodeviews/types.d.ts +1 -0
  36. package/dist/types/plugins/table/ui/TableFloatingControls/CornerControls/index.d.ts +5 -8
  37. package/dist/types/plugins/table/ui/TableFloatingControls/RowControls/index.d.ts +5 -5
  38. package/dist/types-ts4.0/plugins/table/nodeviews/types.d.ts +1 -0
  39. package/dist/types-ts4.0/plugins/table/ui/TableFloatingControls/CornerControls/index.d.ts +5 -8
  40. package/dist/types-ts4.0/plugins/table/ui/TableFloatingControls/RowControls/index.d.ts +5 -5
  41. package/package.json +10 -3
  42. package/src/__tests__/unit/analytics.ts +737 -0
  43. package/src/__tests__/unit/collab.ts +76 -0
  44. package/src/__tests__/unit/commands/sort.ts +230 -0
  45. package/src/__tests__/unit/copy-paste.ts +686 -0
  46. package/src/__tests__/unit/event-handlers/index.ts +106 -0
  47. package/src/__tests__/unit/event-handlers.ts +202 -0
  48. package/src/__tests__/unit/fix-tables.ts +156 -0
  49. package/src/__tests__/unit/floating-toolbar.ts +95 -0
  50. package/src/__tests__/unit/handlers.ts +81 -0
  51. package/src/__tests__/unit/hover-selection.ts +277 -0
  52. package/src/__tests__/unit/index-with-fake-timers.ts +107 -0
  53. package/src/__tests__/unit/index.ts +986 -0
  54. package/src/__tests__/unit/keymap.ts +602 -0
  55. package/src/__tests__/unit/layout.ts +196 -0
  56. package/src/__tests__/unit/nodeviews/cell.ts +167 -0
  57. package/src/__tests__/unit/pm-plugins/table-resizing/utils/resize-state.ts +33 -0
  58. package/src/__tests__/unit/sort-column.ts +512 -0
  59. package/src/__tests__/unit/transforms/delete-columns.ts +499 -0
  60. package/src/__tests__/unit/transforms/delete-rows.ts +557 -0
  61. package/src/__tests__/unit/transforms/merging.ts +374 -0
  62. package/src/__tests__/unit/ui/CornerControls.tsx +80 -0
  63. package/src/__tests__/unit/ui/FloatingContextualButton.tsx +95 -0
  64. package/src/__tests__/unit/ui/FloatingDeleteButton.tsx +175 -0
  65. package/src/__tests__/unit/ui/FloatingInsertButton.tsx +266 -0
  66. package/src/__tests__/unit/ui/RowControls.tsx +301 -0
  67. package/src/__tests__/unit/ui/TableFloatingControls.tsx +93 -0
  68. package/src/__tests__/unit/undo-redo.ts +202 -0
  69. package/src/__tests__/unit/utils/dom.ts +286 -0
  70. package/src/__tests__/unit/utils/nodes.ts +59 -0
  71. package/src/__tests__/unit/utils/row-controls.ts +176 -0
  72. package/src/__tests__/unit/utils/table.ts +93 -0
  73. package/src/__tests__/unit/utils.ts +652 -0
  74. package/src/plugins/table/__tests__/unit/commands/insert.ts +2 -2
  75. package/src/plugins/table/__tests__/unit/commands.ts +2 -2
  76. package/src/plugins/table/__tests__/unit/nodeviews/TableComponent.tsx +2 -2
  77. package/src/plugins/table/__tests__/unit/nodeviews/table.ts +1 -0
  78. package/src/plugins/table/event-handlers.ts +5 -6
  79. package/src/plugins/table/nodeviews/table.tsx +7 -0
  80. package/src/plugins/table/nodeviews/tableCell.tsx +5 -4
  81. package/src/plugins/table/nodeviews/types.ts +1 -0
  82. package/src/plugins/table/pm-plugins/table-resizing/utils/column-state.ts +1 -1
  83. package/src/plugins/table/pm-plugins/table-resizing/utils/resize-logic.ts +6 -2
  84. package/src/plugins/table/toolbar.ts +0 -1
  85. package/src/plugins/table/ui/FloatingContextualMenu/__tests__/ContextualMenu.tsx +1 -1
  86. package/src/plugins/table/ui/FloatingContextualMenu/__tests__/FloatingContextualMenu.tsx +1 -1
  87. package/src/plugins/table/ui/TableFloatingControls/CornerControls/index.tsx +19 -1
  88. package/src/plugins/table/ui/TableFloatingControls/RowControls/index.tsx +16 -1
  89. package/src/plugins/table/ui/TableFloatingControls/index.tsx +2 -2
  90. package/src/plugins/table/utils/column-controls.ts +1 -1
@@ -0,0 +1,557 @@
1
+ import { Rect } from '@atlaskit/editor-tables/table-map';
2
+ import { getSelectionRect } from '@atlaskit/editor-tables/utils';
3
+ import {
4
+ createProsemirrorEditorFactory,
5
+ Preset,
6
+ LightEditorPlugin,
7
+ } from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
8
+ import {
9
+ doc,
10
+ p,
11
+ table,
12
+ tr,
13
+ td,
14
+ th,
15
+ thEmpty,
16
+ tdEmpty,
17
+ DocBuilder,
18
+ } from '@atlaskit/editor-test-helpers/doc-builder';
19
+ import { uuid } from '@atlaskit/adf-schema';
20
+ import { TablePluginState } from '../../../plugins/table/types';
21
+ import { deleteRows } from '../../../plugins/table/transforms';
22
+ import { pluginKey } from '../../../plugins/table/pm-plugins/plugin-key';
23
+ import { PluginKey } from 'prosemirror-state';
24
+ import tablePlugin from '../../../plugins/table-plugin';
25
+
26
+ const rowsToRect = (rows: Array<number>, noOfColumns: number): Rect => ({
27
+ left: 0,
28
+ right: noOfColumns,
29
+ top: Math.min(...rows),
30
+ bottom: Math.max(...rows) + 1,
31
+ });
32
+
33
+ const TABLE_LOCAL_ID = 'test-table-local-id';
34
+
35
+ describe('table plugin -> transforms -> delete rows', () => {
36
+ beforeAll(() => {
37
+ uuid.setStatic(TABLE_LOCAL_ID);
38
+ });
39
+
40
+ afterAll(() => {
41
+ uuid.setStatic(false);
42
+ });
43
+ const createEditor = createProsemirrorEditorFactory();
44
+ const preset = new Preset<LightEditorPlugin>().add([tablePlugin]);
45
+
46
+ const editor = (doc: DocBuilder) =>
47
+ createEditor<TablePluginState, PluginKey>({
48
+ doc,
49
+ preset,
50
+ pluginKey,
51
+ });
52
+
53
+ describe('when selection rect is given', () => {
54
+ describe('when the first row is deleted', () => {
55
+ it('should delete the row and move cursor to the first row', () => {
56
+ const {
57
+ editorView,
58
+ refs: { nextCursorPos },
59
+ } = editor(
60
+ doc(
61
+ p('text'),
62
+ table()(
63
+ tr(td({})(p('{nextCursorPos}a1')), tdEmpty),
64
+ tr(td({})(p('b1')), tdEmpty),
65
+ tr(td({})(p('c1')), tdEmpty),
66
+ ),
67
+ ),
68
+ );
69
+ const { state, dispatch } = editorView;
70
+ dispatch(deleteRows(rowsToRect([0], 3))(state.tr));
71
+ expect(editorView.state.doc).toEqualDocument(
72
+ doc(
73
+ p('text'),
74
+ table({ localId: TABLE_LOCAL_ID })(
75
+ tr(td({})(p('b1')), tdEmpty),
76
+ tr(td({})(p('c1')), tdEmpty),
77
+ ),
78
+ ),
79
+ );
80
+ expect(editorView.state.selection.from).toEqual(nextCursorPos);
81
+ });
82
+ });
83
+
84
+ describe('when the middle row is deleted', () => {
85
+ it('should delete the row and move cursor to the first row', () => {
86
+ const {
87
+ editorView,
88
+ refs: { nextCursorPos },
89
+ } = editor(
90
+ doc(
91
+ p('text'),
92
+ table()(
93
+ tr(td({})(p('{nextCursorPos}a1')), tdEmpty),
94
+ tr(td({})(p('b1')), tdEmpty),
95
+ tr(td({})(p('c1')), tdEmpty),
96
+ ),
97
+ ),
98
+ );
99
+ const { state, dispatch } = editorView;
100
+ dispatch(deleteRows(rowsToRect([1], 3))(state.tr));
101
+ expect(editorView.state.doc).toEqualDocument(
102
+ doc(
103
+ p('text'),
104
+ table({ localId: TABLE_LOCAL_ID })(
105
+ tr(td({})(p('a1')), tdEmpty),
106
+ tr(td({})(p('c1')), tdEmpty),
107
+ ),
108
+ ),
109
+ );
110
+ expect(editorView.state.selection.from).toEqual(nextCursorPos);
111
+ });
112
+ });
113
+
114
+ describe('when multiple rows are selected', () => {
115
+ it('should delete those rows', () => {
116
+ const { editorView } = editor(
117
+ doc(
118
+ p('text'),
119
+ table()(
120
+ tr(td()(p('a1')), td()(p('a2'))),
121
+ tr(td()(p('b1')), td()(p('b2'))),
122
+ tr(td()(p('c1')), td()(p('c2'))),
123
+ ),
124
+ ),
125
+ );
126
+ const { state, dispatch } = editorView;
127
+ dispatch(deleteRows(rowsToRect([0, 1], 3))(state.tr));
128
+ expect(editorView.state.doc).toEqualDocument(
129
+ doc(
130
+ p('text'),
131
+ table({ localId: TABLE_LOCAL_ID })(
132
+ tr(td()(p('c1')), td()(p('c2'))),
133
+ ),
134
+ ),
135
+ );
136
+ });
137
+ });
138
+ });
139
+
140
+ describe('when one row is selected', () => {
141
+ it('should delete the row', () => {
142
+ const { editorView } = editor(
143
+ doc(
144
+ p('text'),
145
+ table()(
146
+ tr(td({})(p('a1{<cell}')), tdEmpty, td({})(p('{cell>}a3'))),
147
+ tr(td({})(p('b1')), td({})(p('b2')), td({})(p('b3'))),
148
+ ),
149
+ ),
150
+ );
151
+ const { state, dispatch } = editorView;
152
+ dispatch(deleteRows(getSelectionRect(state.selection)!)(state.tr));
153
+ expect(editorView.state.doc).toEqualDocument(
154
+ doc(
155
+ p('text'),
156
+ table({ localId: TABLE_LOCAL_ID })(
157
+ tr(td({})(p('b1')), td({})(p('b2')), td({})(p('b3'))),
158
+ ),
159
+ ),
160
+ );
161
+ });
162
+ });
163
+
164
+ describe('when multiple rows are selected', () => {
165
+ it('should delete these rows', () => {
166
+ const { editorView } = editor(
167
+ doc(
168
+ p('text'),
169
+ table()(
170
+ tr(td({})(p('{<cell}a1')), td({})(p('a2'))),
171
+ tr(td({})(p('b1')), td({})(p('{cell>}b2'))),
172
+ tr(td({})(p('c1')), td({})(p('c2'))),
173
+ ),
174
+ ),
175
+ );
176
+ const { state, dispatch } = editorView;
177
+ dispatch(deleteRows(getSelectionRect(state.selection)!)(state.tr));
178
+ expect(editorView.state.doc).toEqualDocument(
179
+ doc(
180
+ p('text'),
181
+ table({ localId: TABLE_LOCAL_ID })(
182
+ tr(td({})(p('c1')), td({})(p('c2'))),
183
+ ),
184
+ ),
185
+ );
186
+ });
187
+ });
188
+
189
+ describe('when some of the rows are merged', () => {
190
+ it('should delete rows and update rowspans of cells DOM nodes', () => {
191
+ const { editorView } = editor(
192
+ doc(
193
+ p('text'),
194
+ table()(
195
+ tr(td({ rowspan: 2 })(p('{<cell}c1')), td({})(p('c2'))),
196
+ tr(td({})(p('{cell>}c3'))),
197
+ tr(td({})(p('c4')), td({})(p('c5'))),
198
+ ),
199
+ ),
200
+ );
201
+ const { state, dispatch } = editorView;
202
+ dispatch(deleteRows(getSelectionRect(state.selection)!)(state.tr));
203
+ expect(editorView.state.doc).toEqualDocument(
204
+ doc(
205
+ p('text'),
206
+ table({ localId: TABLE_LOCAL_ID })(
207
+ tr(td({})(p('c4')), td({})(p('c5'))),
208
+ ),
209
+ ),
210
+ );
211
+ const cells = editorView.dom.querySelectorAll('td');
212
+ for (let i = 0, count = cells.length; i < count; i++) {
213
+ const cell = cells[i] as HTMLElement;
214
+ expect(cell.getAttribute('rowspan')).not.toEqual('2');
215
+ }
216
+ });
217
+
218
+ describe('when after deleting the last row table has columns where all cells have colspan > 1', () => {
219
+ it('should decrement colspan of these cells', () => {
220
+ const { editorView } = editor(
221
+ doc(
222
+ p('text'),
223
+ table()(
224
+ tr(td({ colspan: 2 })(p('a1')), td({})(p('a3'))),
225
+ tr(td({ colspan: 2 })(p('b1')), tdEmpty),
226
+ tr(td({})(p('c1{cell>}')), tdEmpty, td({})(p('{<cell}c3'))),
227
+ ),
228
+ ),
229
+ );
230
+ const { state, dispatch } = editorView;
231
+ dispatch(deleteRows(getSelectionRect(state.selection)!)(state.tr));
232
+ expect(editorView.state.doc).toEqualDocument(
233
+ doc(
234
+ p('text'),
235
+ table({ localId: TABLE_LOCAL_ID })(
236
+ tr(td({})(p('a1')), td({})(p('a3'))),
237
+ tr(td({})(p('b1')), tdEmpty),
238
+ ),
239
+ ),
240
+ );
241
+ });
242
+ });
243
+
244
+ describe('when after deleting the first row table has columns where all cells have colspan > 1', () => {
245
+ it('should decrement colspan of these cells', () => {
246
+ const { editorView } = editor(
247
+ doc(
248
+ p('text'),
249
+ table()(
250
+ tr(td({})(p('a1{<cell}')), tdEmpty, td({})(p('{cell>}a2'))),
251
+ tr(td({ colspan: 2 })(p('b1')), td({})(p('b3'))),
252
+ tr(td({ colspan: 2 })(p('c1')), td({})(p('c3'))),
253
+ ),
254
+ ),
255
+ );
256
+ const { state, dispatch } = editorView;
257
+ dispatch(deleteRows(getSelectionRect(state.selection)!)(state.tr));
258
+ expect(editorView.state.doc).toEqualDocument(
259
+ doc(
260
+ p('text'),
261
+ table({ localId: TABLE_LOCAL_ID })(
262
+ tr(td({})(p('b1')), td({})(p('b3'))),
263
+ tr(td({})(p('c1')), td({})(p('c3'))),
264
+ ),
265
+ ),
266
+ );
267
+ });
268
+ });
269
+
270
+ describe('when isHeaderRowRequired = true (Bitbucket)', () => {
271
+ const isHeaderRowRequired = true;
272
+
273
+ describe('when only header row is selected', () => {
274
+ it('should do nothing', () => {
275
+ const { editorView } = editor(
276
+ doc(table()(tr(thEmpty), tr(tdEmpty), tr(tdEmpty))),
277
+ );
278
+ const { state, dispatch } = editorView;
279
+ dispatch(
280
+ deleteRows(rowsToRect([0], 3), isHeaderRowRequired)(state.tr),
281
+ );
282
+ expect(editorView.state.doc).toEqualDocument(
283
+ doc(
284
+ table({ localId: TABLE_LOCAL_ID })(
285
+ tr(thEmpty),
286
+ tr(tdEmpty),
287
+ tr(tdEmpty),
288
+ ),
289
+ ),
290
+ );
291
+ });
292
+ });
293
+
294
+ describe('when header row and other rows are selected', () => {
295
+ it('should remove selected rows except the header row', () => {
296
+ const { editorView } = editor(
297
+ doc(
298
+ table()(
299
+ tr(th({})(p('header{<cell}')), thEmpty),
300
+ tr(td({})(p('b1{cell>}')), tdEmpty),
301
+ tr(td({})(p('c1')), tdEmpty),
302
+ ),
303
+ ),
304
+ );
305
+ const { state, dispatch } = editorView;
306
+ dispatch(
307
+ deleteRows(
308
+ getSelectionRect(state.selection)!,
309
+ isHeaderRowRequired,
310
+ )(state.tr),
311
+ );
312
+ expect(editorView.state.doc).toEqualDocument(
313
+ doc(
314
+ table({ localId: TABLE_LOCAL_ID })(
315
+ tr(th({})(p('header')), thEmpty),
316
+ tr(td({})(p('c1')), tdEmpty),
317
+ ),
318
+ ),
319
+ );
320
+ });
321
+ });
322
+ });
323
+
324
+ describe('when a row-spanning cell is deleted', () => {
325
+ describe('when this cell has colspan = 1', () => {
326
+ it('should append missing cells to the rows below deleted row', () => {
327
+ const { editorView } = editor(
328
+ doc(
329
+ table()(
330
+ tr(
331
+ td({ colwidth: [110] })(p('a1')),
332
+ td({ colwidth: [120], rowspan: 3 })(p('a2')),
333
+ td({ colwidth: [130] })(p('a3')),
334
+ ),
335
+ tr(
336
+ td({ colwidth: [110] })(p('b1')),
337
+ td({ colwidth: [130] })(p('b3')),
338
+ ),
339
+ tr(
340
+ td({ colwidth: [110] })(p('c1')),
341
+ td({ colwidth: [130] })(p('c3')),
342
+ ),
343
+ ),
344
+ ),
345
+ );
346
+ const { state, dispatch } = editorView;
347
+ dispatch(deleteRows(rowsToRect([0], 3))(state.tr));
348
+ expect(editorView.state.doc).toEqualDocument(
349
+ doc(
350
+ table({ localId: TABLE_LOCAL_ID })(
351
+ tr(
352
+ td({ colwidth: [110] })(p('b1')),
353
+ td({ colwidth: [120] })(p('')),
354
+ td({ colwidth: [130] })(p('b3')),
355
+ ),
356
+ tr(
357
+ td({ colwidth: [110] })(p('c1')),
358
+ td({ colwidth: [120] })(p('')),
359
+ td({ colwidth: [130] })(p('c3')),
360
+ ),
361
+ ),
362
+ ),
363
+ );
364
+ });
365
+ });
366
+
367
+ describe('when this cell has colspan > 1', () => {
368
+ it('should append missing cells to the rows below deleted row', () => {
369
+ const { editorView } = editor(
370
+ doc(
371
+ table()(
372
+ tr(
373
+ td({ colwidth: [110] })(p('a1')),
374
+ td({ colwidth: [120, 130], rowspan: 3, colspan: 2 })(p('a2')),
375
+ td({ colwidth: [140] })(p('a4')),
376
+ ),
377
+ tr(
378
+ td({ colwidth: [110] })(p('b1')),
379
+ td({ colwidth: [140] })(p('b4')),
380
+ ),
381
+ tr(
382
+ td({ colwidth: [110] })(p('c1')),
383
+ td({ colwidth: [140] })(p('c4')),
384
+ ),
385
+ tr(
386
+ td({ colwidth: [110] })(p('d1')),
387
+ td({ colwidth: [120] })(p('d2')),
388
+ td({ colwidth: [130] })(p('d3')),
389
+ td({ colwidth: [140] })(p('d4')),
390
+ ),
391
+ ),
392
+ ),
393
+ );
394
+ const { state, dispatch } = editorView;
395
+ dispatch(deleteRows(rowsToRect([0], 3))(state.tr));
396
+ expect(editorView.state.doc).toEqualDocument(
397
+ doc(
398
+ table({ localId: TABLE_LOCAL_ID })(
399
+ tr(
400
+ td({ colwidth: [110] })(p('b1')),
401
+ td({ colwidth: [120] })(p('')),
402
+ td({ colwidth: [130] })(p('')),
403
+ td({ colwidth: [140] })(p('b4')),
404
+ ),
405
+ tr(
406
+ td({ colwidth: [110] })(p('c1')),
407
+ td({ colwidth: [120] })(p('')),
408
+ td({ colwidth: [130] })(p('')),
409
+ td({ colwidth: [140] })(p('c4')),
410
+ ),
411
+ tr(
412
+ td({ colwidth: [110] })(p('d1')),
413
+ td({ colwidth: [120] })(p('d2')),
414
+ td({ colwidth: [130] })(p('d3')),
415
+ td({ colwidth: [140] })(p('d4')),
416
+ ),
417
+ ),
418
+ ),
419
+ );
420
+ });
421
+ });
422
+ });
423
+
424
+ describe('when a row-spanning cell overlaps deleted row from the row above', () => {
425
+ describe('when this cell has colspan = 1', () => {
426
+ it('should decrement the rowspan of that cell', () => {
427
+ const { editorView } = editor(
428
+ doc(
429
+ table()(
430
+ tr(
431
+ td({ colwidth: [110] })(p('a1')),
432
+ td({ colwidth: [120, 130], rowspan: 3, colspan: 2 })(p('a2')),
433
+ td({ colwidth: [140] })(p('a4')),
434
+ ),
435
+ tr(
436
+ td({ colwidth: [110] })(p('b1')),
437
+ td({ colwidth: [140] })(p('b4')),
438
+ ),
439
+ tr(
440
+ td({ colwidth: [110] })(p('c1')),
441
+ td({ colwidth: [140] })(p('c4')),
442
+ ),
443
+ tr(
444
+ td({ colwidth: [110] })(p('d1')),
445
+ td({ colwidth: [120] })(p('d2')),
446
+ td({ colwidth: [130] })(p('d3')),
447
+ td({ colwidth: [140] })(p('d4')),
448
+ ),
449
+ ),
450
+ ),
451
+ );
452
+ const { state, dispatch } = editorView;
453
+ dispatch(deleteRows(rowsToRect([1], 3))(state.tr));
454
+ expect(editorView.state.doc).toEqualDocument(
455
+ doc(
456
+ table({ localId: TABLE_LOCAL_ID })(
457
+ tr(
458
+ td({ colwidth: [110] })(p('a1')),
459
+ td({ colwidth: [120, 130], rowspan: 2, colspan: 2 })(p('a2')),
460
+ td({ colwidth: [140] })(p('a4')),
461
+ ),
462
+ tr(
463
+ td({ colwidth: [110] })(p('c1')),
464
+ td({ colwidth: [140] })(p('c4')),
465
+ ),
466
+ tr(
467
+ td({ colwidth: [110] })(p('d1')),
468
+ td({ colwidth: [120] })(p('d2')),
469
+ td({ colwidth: [130] })(p('d3')),
470
+ td({ colwidth: [140] })(p('d4')),
471
+ ),
472
+ ),
473
+ ),
474
+ );
475
+ });
476
+ });
477
+
478
+ describe('when this cell has colspan > 1', () => {
479
+ it('should decrement the rowspan of that cell', () => {
480
+ const { editorView } = editor(
481
+ doc(
482
+ table()(
483
+ tr(
484
+ td({ colwidth: [110] })(p('a1')),
485
+ td({ colwidth: [120], rowspan: 3 })(p('a2')),
486
+ td({ colwidth: [130] })(p('a3')),
487
+ ),
488
+ tr(
489
+ td({ colwidth: [110] })(p('b1')),
490
+ td({ colwidth: [130] })(p('b3')),
491
+ ),
492
+ tr(
493
+ td({ colwidth: [110] })(p('c1')),
494
+ td({ colwidth: [130] })(p('c3')),
495
+ ),
496
+ ),
497
+ ),
498
+ );
499
+ const { state, dispatch } = editorView;
500
+ dispatch(deleteRows(rowsToRect([1], 3))(state.tr));
501
+ expect(editorView.state.doc).toEqualDocument(
502
+ doc(
503
+ table({ localId: TABLE_LOCAL_ID })(
504
+ tr(
505
+ td({ colwidth: [110] })(p('a1')),
506
+ td({ colwidth: [120], rowspan: 2 })(p('a2')),
507
+ td({ colwidth: [130] })(p('a3')),
508
+ ),
509
+ tr(
510
+ td({ colwidth: [110] })(p('c1')),
511
+ td({ colwidth: [130] })(p('c3')),
512
+ ),
513
+ ),
514
+ ),
515
+ );
516
+ });
517
+ });
518
+ });
519
+
520
+ describe('when a row-spanning cell overlaps two deleted rows from the row above', () => {
521
+ it('should decrement the rowspan of that cell twice', () => {
522
+ const { editorView } = editor(
523
+ doc(
524
+ table()(
525
+ tr(
526
+ td({ colwidth: [110] })(p('a1')),
527
+ td({ colwidth: [120], rowspan: 3 })(p('a2')),
528
+ td({ colwidth: [130] })(p('a3')),
529
+ ),
530
+ tr(
531
+ td({ colwidth: [110] })(p('b1')),
532
+ td({ colwidth: [130] })(p('b3')),
533
+ ),
534
+ tr(
535
+ td({ colwidth: [110] })(p('c1')),
536
+ td({ colwidth: [130] })(p('c3')),
537
+ ),
538
+ ),
539
+ ),
540
+ );
541
+ const { state, dispatch } = editorView;
542
+ dispatch(deleteRows(rowsToRect([1, 2], 3))(state.tr));
543
+ expect(editorView.state.doc).toEqualDocument(
544
+ doc(
545
+ table({ localId: TABLE_LOCAL_ID })(
546
+ tr(
547
+ td({ colwidth: [110] })(p('a1')),
548
+ td({ colwidth: [120] })(p('a2')),
549
+ td({ colwidth: [130] })(p('a3')),
550
+ ),
551
+ ),
552
+ ),
553
+ );
554
+ });
555
+ });
556
+ });
557
+ });