@atlaskit/editor-plugin-table 0.0.5 → 0.0.7
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/CHANGELOG.md +17 -0
- package/dist/cjs/plugins/table/commands-with-analytics.js +6 -0
- package/dist/cjs/plugins/table/event-handlers.js +7 -6
- package/dist/cjs/plugins/table/nodeviews/tableCell.js +4 -4
- package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
- package/dist/cjs/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
- package/dist/cjs/plugins/table/utils/column-controls.js +1 -1
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/plugins/table/commands-with-analytics.js +6 -0
- package/dist/es2019/plugins/table/event-handlers.js +8 -7
- package/dist/es2019/plugins/table/nodeviews/tableCell.js +3 -4
- package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
- package/dist/es2019/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
- package/dist/es2019/plugins/table/utils/column-controls.js +1 -1
- package/dist/es2019/version.json +1 -1
- package/dist/esm/plugins/table/commands-with-analytics.js +6 -0
- package/dist/esm/plugins/table/event-handlers.js +8 -7
- package/dist/esm/plugins/table/nodeviews/tableCell.js +3 -4
- package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/column-state.js +1 -1
- package/dist/esm/plugins/table/pm-plugins/table-resizing/utils/resize-logic.js +8 -3
- package/dist/esm/plugins/table/utils/column-controls.js +1 -1
- package/dist/esm/version.json +1 -1
- package/package.json +9 -7
- package/report.api.md +13 -6
- package/src/__tests__/unit/analytics.ts +737 -0
- package/src/__tests__/unit/collab.ts +76 -0
- package/src/__tests__/unit/commands/sort.ts +230 -0
- package/src/__tests__/unit/copy-paste.ts +686 -0
- package/src/__tests__/unit/event-handlers/index.ts +106 -0
- package/src/__tests__/unit/event-handlers.ts +202 -0
- package/src/__tests__/unit/fix-tables.ts +156 -0
- package/src/__tests__/unit/floating-toolbar.ts +95 -0
- package/src/__tests__/unit/handlers.ts +81 -0
- package/src/__tests__/unit/hover-selection.ts +277 -0
- package/src/__tests__/unit/index-with-fake-timers.ts +106 -0
- package/src/__tests__/unit/index.ts +986 -0
- package/src/__tests__/unit/keymap.ts +602 -0
- package/src/__tests__/unit/layout.ts +196 -0
- package/src/__tests__/unit/nodeviews/cell.ts +167 -0
- package/src/__tests__/unit/pm-plugins/table-resizing/utils/resize-state.ts +33 -0
- package/src/__tests__/unit/sort-column.ts +512 -0
- package/src/__tests__/unit/transforms/delete-columns.ts +499 -0
- package/src/__tests__/unit/transforms/delete-rows.ts +557 -0
- package/src/__tests__/unit/transforms/merging.ts +374 -0
- package/src/__tests__/unit/ui/CornerControls.tsx +80 -0
- package/src/__tests__/unit/ui/FloatingContextualButton.tsx +95 -0
- package/src/__tests__/unit/ui/FloatingDeleteButton.tsx +175 -0
- package/src/__tests__/unit/ui/FloatingInsertButton.tsx +266 -0
- package/src/__tests__/unit/ui/RowControls.tsx +301 -0
- package/src/__tests__/unit/ui/TableFloatingControls.tsx +93 -0
- package/src/__tests__/unit/undo-redo.ts +202 -0
- package/src/__tests__/unit/utils/dom.ts +286 -0
- package/src/__tests__/unit/utils/nodes.ts +59 -0
- package/src/__tests__/unit/utils/row-controls.ts +176 -0
- package/src/__tests__/unit/utils/table.ts +93 -0
- package/src/__tests__/unit/utils.ts +652 -0
- package/src/plugins/table/commands-with-analytics.ts +3 -0
- package/src/plugins/table/event-handlers.ts +5 -6
- package/src/plugins/table/nodeviews/tableCell.tsx +5 -4
- package/src/plugins/table/pm-plugins/table-resizing/utils/column-state.ts +1 -1
- package/src/plugins/table/pm-plugins/table-resizing/utils/resize-logic.ts +6 -2
- package/src/plugins/table/utils/column-controls.ts +1 -1
- package/tmp/api-report-tmp.d.ts +91 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { createEditorFactory } from '@atlaskit/editor-test-helpers/create-editor';
|
|
2
|
+
import { mountWithIntl } from '@atlaskit/editor-test-helpers/enzyme';
|
|
3
|
+
import {
|
|
4
|
+
doc,
|
|
5
|
+
p,
|
|
6
|
+
table,
|
|
7
|
+
td,
|
|
8
|
+
tdCursor,
|
|
9
|
+
tdEmpty,
|
|
10
|
+
thEmpty,
|
|
11
|
+
tr,
|
|
12
|
+
DocBuilder,
|
|
13
|
+
} from '@atlaskit/editor-test-helpers/doc-builder';
|
|
14
|
+
import { selectRows } from '@atlaskit/editor-test-helpers/table';
|
|
15
|
+
import { getSelectionRect, selectRow } from '@atlaskit/editor-tables/utils';
|
|
16
|
+
import React from 'react';
|
|
17
|
+
import type { EditorProps } from '@atlaskit/editor-core';
|
|
18
|
+
import { setTextSelection } from '@atlaskit/editor-common/utils';
|
|
19
|
+
import { hoverRows } from '../../../plugins/table/commands';
|
|
20
|
+
import {
|
|
21
|
+
TableCssClassName as ClassName,
|
|
22
|
+
TablePluginState,
|
|
23
|
+
} from '../../../plugins/table/types';
|
|
24
|
+
import TableFloatingControls from '../../../plugins/table/ui/TableFloatingControls';
|
|
25
|
+
import RowControls from '../../../plugins/table/ui/TableFloatingControls/RowControls';
|
|
26
|
+
import { pluginKey } from '../../../plugins/table/pm-plugins/plugin-key';
|
|
27
|
+
import { ReactWrapper } from 'enzyme';
|
|
28
|
+
import tablePlugin from '../../../plugins/table-plugin';
|
|
29
|
+
|
|
30
|
+
const ControlsButton = `.${ClassName.CONTROLS_BUTTON}`;
|
|
31
|
+
const RowControlsButtonWrap = `.${ClassName.ROW_CONTROLS_BUTTON_WRAP}`;
|
|
32
|
+
|
|
33
|
+
describe('RowControls', () => {
|
|
34
|
+
const createEditor = createEditorFactory<TablePluginState>();
|
|
35
|
+
const fakeGetEditorFeatureFlags = jest.fn(() => ({}));
|
|
36
|
+
let floatingControls: ReactWrapper;
|
|
37
|
+
let originalResizeObserver: any;
|
|
38
|
+
|
|
39
|
+
let triggerElementResize = (element: HTMLElement, height: number) => {
|
|
40
|
+
const entries = [
|
|
41
|
+
{
|
|
42
|
+
target: element,
|
|
43
|
+
contentRect: { height },
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
resizeCallback(entries);
|
|
47
|
+
};
|
|
48
|
+
let resizeCallback: (entries: any[]) => {};
|
|
49
|
+
|
|
50
|
+
beforeAll(() => {
|
|
51
|
+
originalResizeObserver = (window as any).ResizeObserver;
|
|
52
|
+
(window as any).ResizeObserver = function resizeObserverMock(
|
|
53
|
+
callback: () => {},
|
|
54
|
+
) {
|
|
55
|
+
this.disconnect = jest.fn();
|
|
56
|
+
this.observe = jest.fn();
|
|
57
|
+
resizeCallback = callback;
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
afterAll(() => {
|
|
62
|
+
(window as any).ResizeObserver = originalResizeObserver;
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
afterEach(() => {
|
|
66
|
+
if (floatingControls && floatingControls.length) {
|
|
67
|
+
floatingControls.unmount();
|
|
68
|
+
}
|
|
69
|
+
jest.clearAllMocks();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const editor = (doc: DocBuilder, props?: EditorProps) => {
|
|
73
|
+
const { featureFlags } = props || {};
|
|
74
|
+
fakeGetEditorFeatureFlags.mockReturnValue(featureFlags || {});
|
|
75
|
+
|
|
76
|
+
return createEditor({
|
|
77
|
+
doc,
|
|
78
|
+
editorProps: {
|
|
79
|
+
allowTables: false,
|
|
80
|
+
dangerouslyAppendPlugins: { __plugins: [tablePlugin()] },
|
|
81
|
+
...props,
|
|
82
|
+
},
|
|
83
|
+
pluginKey,
|
|
84
|
+
});
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
[1, 2, 3].forEach((row) => {
|
|
88
|
+
describe(`when table has ${row} rows`, () => {
|
|
89
|
+
it(`should render ${row} row header buttons`, () => {
|
|
90
|
+
const rows = [tr(tdCursor)];
|
|
91
|
+
for (let i = 1; i < row; i++) {
|
|
92
|
+
rows.push(tr(tdEmpty));
|
|
93
|
+
}
|
|
94
|
+
const { editorView } = editor(doc(p('text'), table()(...rows)));
|
|
95
|
+
floatingControls = mountWithIntl(
|
|
96
|
+
<TableFloatingControls
|
|
97
|
+
tableRef={document.querySelector('table')!}
|
|
98
|
+
tableActive={true}
|
|
99
|
+
editorView={editorView}
|
|
100
|
+
getEditorFeatureFlags={fakeGetEditorFeatureFlags}
|
|
101
|
+
/>,
|
|
102
|
+
);
|
|
103
|
+
expect(floatingControls.find(RowControlsButtonWrap)).toHaveLength(row);
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('does not render rowControls if table is not active', () => {
|
|
109
|
+
const { editorView } = editor(doc(p('text'), table()(tr(tdCursor))));
|
|
110
|
+
floatingControls = mountWithIntl(
|
|
111
|
+
<TableFloatingControls
|
|
112
|
+
tableRef={document.querySelector('table')!}
|
|
113
|
+
tableActive={false}
|
|
114
|
+
editorView={editorView}
|
|
115
|
+
getEditorFeatureFlags={fakeGetEditorFeatureFlags}
|
|
116
|
+
/>,
|
|
117
|
+
);
|
|
118
|
+
expect(floatingControls.find(RowControlsButtonWrap)).toHaveLength(0);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('with tableRenderOptimization enabled', () => {
|
|
122
|
+
it('updates rowControls if table height changes', () => {
|
|
123
|
+
const { editorView } = editor(doc(table()(tr(tdCursor))), {
|
|
124
|
+
featureFlags: { tableRenderOptimization: true },
|
|
125
|
+
});
|
|
126
|
+
floatingControls = mountWithIntl(
|
|
127
|
+
<TableFloatingControls
|
|
128
|
+
tableRef={document.querySelector('table')!}
|
|
129
|
+
tableActive={true}
|
|
130
|
+
editorView={editorView}
|
|
131
|
+
getEditorFeatureFlags={fakeGetEditorFeatureFlags}
|
|
132
|
+
/>,
|
|
133
|
+
);
|
|
134
|
+
const tableElement = editorView.domAtPos(1).node as HTMLElement;
|
|
135
|
+
triggerElementResize(tableElement, 10);
|
|
136
|
+
expect(floatingControls.state('tableHeight')).toBe(10);
|
|
137
|
+
tableElement.style.height = '100px';
|
|
138
|
+
triggerElementResize(tableElement, 100);
|
|
139
|
+
expect(floatingControls.state('tableHeight')).toBe(100);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
[0, 1, 2].forEach((row) => {
|
|
144
|
+
describe(`when HeaderButton in row ${row + 1} is clicked`, () => {
|
|
145
|
+
it('should not move the cursor when hovering controls', () => {
|
|
146
|
+
const { editorView, refs } = editor(
|
|
147
|
+
doc(
|
|
148
|
+
table()(
|
|
149
|
+
tr(thEmpty, td({})(p('{nextPos}')), thEmpty),
|
|
150
|
+
tr(tdCursor, tdEmpty, tdEmpty),
|
|
151
|
+
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
152
|
+
),
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
floatingControls = mountWithIntl(
|
|
157
|
+
<TableFloatingControls
|
|
158
|
+
tableRef={document.querySelector('table')!}
|
|
159
|
+
tableActive={true}
|
|
160
|
+
editorView={editorView}
|
|
161
|
+
getEditorFeatureFlags={fakeGetEditorFeatureFlags}
|
|
162
|
+
/>,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
// move to header row
|
|
166
|
+
const { nextPos } = refs;
|
|
167
|
+
setTextSelection(editorView, nextPos);
|
|
168
|
+
|
|
169
|
+
// now hover the row
|
|
170
|
+
floatingControls
|
|
171
|
+
.find(RowControlsButtonWrap)
|
|
172
|
+
.at(row)
|
|
173
|
+
.find('button')
|
|
174
|
+
.first()
|
|
175
|
+
.simulate('mouseover');
|
|
176
|
+
|
|
177
|
+
// assert the cursor is still in same position
|
|
178
|
+
expect(editorView.state.selection.$from.pos).toBe(nextPos);
|
|
179
|
+
expect(editorView.state.selection.$to.pos).toBe(nextPos);
|
|
180
|
+
|
|
181
|
+
// release the hover
|
|
182
|
+
floatingControls
|
|
183
|
+
.find(RowControlsButtonWrap)
|
|
184
|
+
.at(row)
|
|
185
|
+
.find('button')
|
|
186
|
+
.first()
|
|
187
|
+
.simulate('mouseout');
|
|
188
|
+
|
|
189
|
+
// assert the cursor is still in same position
|
|
190
|
+
expect(editorView.state.selection.$from.pos).toBe(nextPos);
|
|
191
|
+
expect(editorView.state.selection.$to.pos).toBe(nextPos);
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('applies the danger class to the row buttons', () => {
|
|
197
|
+
const { editorView } = editor(
|
|
198
|
+
doc(
|
|
199
|
+
table()(
|
|
200
|
+
tr(thEmpty, td({})(p()), thEmpty),
|
|
201
|
+
tr(tdCursor, tdEmpty, tdEmpty),
|
|
202
|
+
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
203
|
+
),
|
|
204
|
+
),
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
floatingControls = mountWithIntl(
|
|
208
|
+
<RowControls
|
|
209
|
+
tableRef={document.querySelector('table')!}
|
|
210
|
+
editorView={editorView}
|
|
211
|
+
hoverRows={(rows, danger) => {
|
|
212
|
+
hoverRows(rows, danger)(editorView.state, editorView.dispatch);
|
|
213
|
+
}}
|
|
214
|
+
hoveredRows={[0, 1]}
|
|
215
|
+
isInDanger={true}
|
|
216
|
+
selectRow={(row) => {
|
|
217
|
+
editorView.dispatch(selectRow(row)(editorView.state.tr));
|
|
218
|
+
}}
|
|
219
|
+
/>,
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
floatingControls
|
|
223
|
+
.find(RowControlsButtonWrap)
|
|
224
|
+
.slice(0, 2)
|
|
225
|
+
.forEach((buttonWrap) => {
|
|
226
|
+
expect(buttonWrap.hasClass('danger')).toBe(true);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
describe('row shift selection', () => {
|
|
231
|
+
it('should shift select rows after the currently selected row', () => {
|
|
232
|
+
const { editorView } = editor(
|
|
233
|
+
doc(
|
|
234
|
+
table()(
|
|
235
|
+
tr(thEmpty, thEmpty, thEmpty),
|
|
236
|
+
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
237
|
+
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
238
|
+
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
239
|
+
),
|
|
240
|
+
),
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
selectRows([0])(editorView.state, editorView.dispatch);
|
|
244
|
+
floatingControls = mountWithIntl(
|
|
245
|
+
<RowControls
|
|
246
|
+
tableRef={document.querySelector('table')!}
|
|
247
|
+
editorView={editorView}
|
|
248
|
+
hoverRows={(rows, danger) => {
|
|
249
|
+
hoverRows(rows, danger)(editorView.state, editorView.dispatch);
|
|
250
|
+
}}
|
|
251
|
+
selectRow={(row, expand) => {
|
|
252
|
+
editorView.dispatch(selectRow(row, expand)(editorView.state.tr));
|
|
253
|
+
}}
|
|
254
|
+
/>,
|
|
255
|
+
);
|
|
256
|
+
|
|
257
|
+
floatingControls
|
|
258
|
+
.find(ControlsButton)
|
|
259
|
+
.at(2)
|
|
260
|
+
.simulate('click', { shiftKey: true });
|
|
261
|
+
|
|
262
|
+
const rect = getSelectionRect(editorView.state.selection);
|
|
263
|
+
expect(rect).toEqual({ left: 0, top: 0, right: 3, bottom: 3 });
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('should shift select row before the currently selected row', () => {
|
|
267
|
+
const { editorView } = editor(
|
|
268
|
+
doc(
|
|
269
|
+
table()(
|
|
270
|
+
tr(thEmpty, thEmpty, thEmpty),
|
|
271
|
+
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
272
|
+
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
273
|
+
tr(tdEmpty, tdEmpty, tdEmpty),
|
|
274
|
+
),
|
|
275
|
+
),
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
selectRows([2])(editorView.state, editorView.dispatch);
|
|
279
|
+
floatingControls = mountWithIntl(
|
|
280
|
+
<RowControls
|
|
281
|
+
tableRef={document.querySelector('table')!}
|
|
282
|
+
editorView={editorView}
|
|
283
|
+
hoverRows={(rows, danger) => {
|
|
284
|
+
hoverRows(rows, danger)(editorView.state, editorView.dispatch);
|
|
285
|
+
}}
|
|
286
|
+
selectRow={(row, expand) => {
|
|
287
|
+
editorView.dispatch(selectRow(row, expand)(editorView.state.tr));
|
|
288
|
+
}}
|
|
289
|
+
/>,
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
floatingControls
|
|
293
|
+
.find(ControlsButton)
|
|
294
|
+
.first()
|
|
295
|
+
.simulate('click', { shiftKey: true });
|
|
296
|
+
|
|
297
|
+
const rect = getSelectionRect(editorView.state.selection);
|
|
298
|
+
expect(rect).toEqual({ left: 0, top: 0, right: 3, bottom: 3 });
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { shallow, mount } from 'enzyme';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
createProsemirrorEditorFactory,
|
|
6
|
+
Preset,
|
|
7
|
+
LightEditorPlugin,
|
|
8
|
+
} from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
|
|
9
|
+
import {
|
|
10
|
+
doc,
|
|
11
|
+
p,
|
|
12
|
+
table,
|
|
13
|
+
tr,
|
|
14
|
+
tdEmpty,
|
|
15
|
+
tdCursor,
|
|
16
|
+
DocBuilder,
|
|
17
|
+
} from '@atlaskit/editor-test-helpers/doc-builder';
|
|
18
|
+
|
|
19
|
+
import { TablePluginState } from '../../../plugins/table/types';
|
|
20
|
+
import { hoverTable } from '../../../plugins/table/commands';
|
|
21
|
+
import TableFloatingControls from '../../../plugins/table/ui/TableFloatingControls';
|
|
22
|
+
import CornerControls from '../../../plugins/table/ui/TableFloatingControls/CornerControls';
|
|
23
|
+
import RowControls from '../../../plugins/table/ui/TableFloatingControls/RowControls';
|
|
24
|
+
import { pluginKey } from '../../../plugins/table/pm-plugins/plugin-key';
|
|
25
|
+
import { getDecorations } from '../../../plugins/table/pm-plugins/decorations/plugin';
|
|
26
|
+
import tablePlugin from '../../../plugins/table-plugin';
|
|
27
|
+
import { PluginKey } from 'prosemirror-state';
|
|
28
|
+
|
|
29
|
+
describe('TableFloatingControls', () => {
|
|
30
|
+
const createEditor = createProsemirrorEditorFactory();
|
|
31
|
+
const fakeGetEditorFeatureFlags = () => ({});
|
|
32
|
+
const preset = new Preset<LightEditorPlugin>().add(tablePlugin);
|
|
33
|
+
|
|
34
|
+
const editor = (doc: DocBuilder) =>
|
|
35
|
+
createEditor<TablePluginState, PluginKey>({
|
|
36
|
+
doc,
|
|
37
|
+
preset,
|
|
38
|
+
pluginKey: pluginKey,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
describe('when tableRef is undefined', () => {
|
|
42
|
+
it('should not render table header', () => {
|
|
43
|
+
const { editorView } = editor(
|
|
44
|
+
doc(p('text'), table()(tr(tdEmpty, tdEmpty, tdEmpty))),
|
|
45
|
+
);
|
|
46
|
+
const floatingControls = mount(
|
|
47
|
+
<TableFloatingControls
|
|
48
|
+
editorView={editorView}
|
|
49
|
+
getEditorFeatureFlags={fakeGetEditorFeatureFlags}
|
|
50
|
+
/>,
|
|
51
|
+
);
|
|
52
|
+
expect(floatingControls.html()).toEqual(null);
|
|
53
|
+
floatingControls.unmount();
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('when tableRef is defined', () => {
|
|
58
|
+
it('should render CornerControls and RowControls', () => {
|
|
59
|
+
const { editorView } = editor(
|
|
60
|
+
doc(p('text'), table()(tr(tdEmpty, tdEmpty, tdEmpty))),
|
|
61
|
+
);
|
|
62
|
+
const floatingControls = shallow(
|
|
63
|
+
<TableFloatingControls
|
|
64
|
+
tableRef={document.createElement('table')}
|
|
65
|
+
tableActive={true}
|
|
66
|
+
editorView={editorView}
|
|
67
|
+
getEditorFeatureFlags={fakeGetEditorFeatureFlags}
|
|
68
|
+
/>,
|
|
69
|
+
);
|
|
70
|
+
expect(floatingControls.find(CornerControls).length).toEqual(1);
|
|
71
|
+
expect(floatingControls.find(RowControls).length).toEqual(1);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
describe('when delete icon is hovered', () => {
|
|
76
|
+
it('should add a node decoration to table nodeView with class="danger"', () => {
|
|
77
|
+
const { editorView } = editor(
|
|
78
|
+
doc(
|
|
79
|
+
p('text'),
|
|
80
|
+
table()(
|
|
81
|
+
tr(tdCursor, tdEmpty),
|
|
82
|
+
tr(tdEmpty, tdEmpty),
|
|
83
|
+
tr(tdEmpty, tdEmpty),
|
|
84
|
+
),
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
hoverTable(true)(editorView.state, editorView.dispatch);
|
|
88
|
+
const decorationSet = getDecorations(editorView.state);
|
|
89
|
+
const decoration = decorationSet.find()[0] as any;
|
|
90
|
+
expect(decoration.type.attrs.class.indexOf('danger')).toBeGreaterThan(-1);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { createEditorFactory } from '@atlaskit/editor-test-helpers/create-editor';
|
|
2
|
+
import {
|
|
3
|
+
doc,
|
|
4
|
+
p,
|
|
5
|
+
table,
|
|
6
|
+
tr,
|
|
7
|
+
th,
|
|
8
|
+
DocBuilder,
|
|
9
|
+
thEmpty,
|
|
10
|
+
td,
|
|
11
|
+
tdCursor,
|
|
12
|
+
tdEmpty,
|
|
13
|
+
} from '@atlaskit/editor-test-helpers/doc-builder';
|
|
14
|
+
import { EditorView } from 'prosemirror-view';
|
|
15
|
+
import { TablePluginState } from '../../plugins/table/types';
|
|
16
|
+
import { pluginKey as tablePluginKey } from '../../plugins/table/pm-plugins/plugin-key';
|
|
17
|
+
import { redo, undo } from 'prosemirror-history';
|
|
18
|
+
import { insertColumn } from '../../plugins/table/commands';
|
|
19
|
+
import { deleteColumns } from '../../plugins/table/transforms';
|
|
20
|
+
import { colsToRect } from '../../plugins/table/utils/table';
|
|
21
|
+
import sendKeyToPm from '@atlaskit/editor-test-helpers/send-key-to-pm';
|
|
22
|
+
import clone from 'lodash/clone';
|
|
23
|
+
import tablePlugin from '../../plugins/table';
|
|
24
|
+
|
|
25
|
+
const TABLE_LOCAL_ID = 'test-table-local-id';
|
|
26
|
+
|
|
27
|
+
const getEditorContainerWidth = () => {
|
|
28
|
+
return {
|
|
29
|
+
width: 500,
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
// HELPERS
|
|
33
|
+
const INSERT_COLUMN = (editorView: EditorView) =>
|
|
34
|
+
insertColumn(getEditorContainerWidth)(1)(
|
|
35
|
+
editorView.state,
|
|
36
|
+
editorView.dispatch,
|
|
37
|
+
editorView,
|
|
38
|
+
);
|
|
39
|
+
const DELETE_COLUMN = (editorView: EditorView) => {
|
|
40
|
+
const { state, dispatch } = editorView;
|
|
41
|
+
dispatch(deleteColumns(colsToRect([0], 1))(state.tr));
|
|
42
|
+
};
|
|
43
|
+
const SHORTCUT_ADD_COLUMN_BEFORE = (editorView: EditorView) =>
|
|
44
|
+
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowLeft');
|
|
45
|
+
const SHORTCUT_ADD_COLUMN_AFTER = (editorView: EditorView) =>
|
|
46
|
+
sendKeyToPm(editorView, 'Ctrl-Alt-ArrowRight');
|
|
47
|
+
|
|
48
|
+
describe('undo/redo with tables', () => {
|
|
49
|
+
const createEditor = createEditorFactory<TablePluginState>();
|
|
50
|
+
const editor = (doc: DocBuilder) => {
|
|
51
|
+
const tableOptions = {
|
|
52
|
+
advanced: true,
|
|
53
|
+
allowColumnSorting: true,
|
|
54
|
+
};
|
|
55
|
+
return createEditor({
|
|
56
|
+
doc,
|
|
57
|
+
editorProps: {
|
|
58
|
+
allowTables: false,
|
|
59
|
+
dangerouslyAppendPlugins: {
|
|
60
|
+
__plugins: [tablePlugin({ tableOptions })],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
pluginKey: tablePluginKey,
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
type TestCase = [
|
|
67
|
+
string,
|
|
68
|
+
{
|
|
69
|
+
before: DocBuilder;
|
|
70
|
+
action: Function;
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
const case01: TestCase = [
|
|
75
|
+
'when table has colwidth attribute and new col has been inserted',
|
|
76
|
+
{
|
|
77
|
+
before: doc(
|
|
78
|
+
table({
|
|
79
|
+
localId: TABLE_LOCAL_ID,
|
|
80
|
+
})(tr(th({ colwidth: [285] })(p('')), th({ colwidth: [1310] })(p('')))),
|
|
81
|
+
),
|
|
82
|
+
action: INSERT_COLUMN,
|
|
83
|
+
},
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
const case02: TestCase = [
|
|
87
|
+
'when table has colwidth attribute and deleting a col',
|
|
88
|
+
{
|
|
89
|
+
before: doc(
|
|
90
|
+
table({
|
|
91
|
+
localId: TABLE_LOCAL_ID,
|
|
92
|
+
})(tr(th({ colwidth: [285] })(p('')), th({ colwidth: [1310] })(p('')))),
|
|
93
|
+
),
|
|
94
|
+
action: DELETE_COLUMN,
|
|
95
|
+
},
|
|
96
|
+
];
|
|
97
|
+
|
|
98
|
+
const case03: TestCase = [
|
|
99
|
+
'when table has no colwidth attribute and new col is inserted',
|
|
100
|
+
{
|
|
101
|
+
before: doc(
|
|
102
|
+
table({
|
|
103
|
+
localId: TABLE_LOCAL_ID,
|
|
104
|
+
})(tr(thEmpty, thEmpty)),
|
|
105
|
+
),
|
|
106
|
+
action: INSERT_COLUMN,
|
|
107
|
+
},
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
const case04: TestCase = [
|
|
111
|
+
'when table has no colwidth attribute and col is deleted',
|
|
112
|
+
{
|
|
113
|
+
before: doc(
|
|
114
|
+
table({
|
|
115
|
+
localId: TABLE_LOCAL_ID,
|
|
116
|
+
})(tr(thEmpty, thEmpty)),
|
|
117
|
+
),
|
|
118
|
+
action: DELETE_COLUMN,
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
const case05: TestCase = [
|
|
123
|
+
'when table has colwidth attribute and col is inserted after selection via shortcuts',
|
|
124
|
+
{
|
|
125
|
+
before: doc(
|
|
126
|
+
table({
|
|
127
|
+
localId: TABLE_LOCAL_ID,
|
|
128
|
+
})(
|
|
129
|
+
tr(
|
|
130
|
+
td({ colwidth: [194] })(p('{<>}')),
|
|
131
|
+
td({ colwidth: [564] })(p('')),
|
|
132
|
+
),
|
|
133
|
+
),
|
|
134
|
+
),
|
|
135
|
+
action: SHORTCUT_ADD_COLUMN_AFTER,
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
|
|
139
|
+
const case06: TestCase = [
|
|
140
|
+
'when table has colwidth attribute and col is inserted before selection via shortcuts',
|
|
141
|
+
{
|
|
142
|
+
before: doc(
|
|
143
|
+
table({
|
|
144
|
+
localId: TABLE_LOCAL_ID,
|
|
145
|
+
})(
|
|
146
|
+
tr(
|
|
147
|
+
td({ colwidth: [194] })(p('{<>}')),
|
|
148
|
+
td({ colwidth: [564] })(p('')),
|
|
149
|
+
),
|
|
150
|
+
),
|
|
151
|
+
),
|
|
152
|
+
action: SHORTCUT_ADD_COLUMN_BEFORE,
|
|
153
|
+
},
|
|
154
|
+
];
|
|
155
|
+
|
|
156
|
+
const case07: TestCase = [
|
|
157
|
+
'when table has no colwidth attribute and col is inserted before selection via shortcuts',
|
|
158
|
+
{
|
|
159
|
+
before: doc(
|
|
160
|
+
table({
|
|
161
|
+
localId: TABLE_LOCAL_ID,
|
|
162
|
+
})(tr(tdCursor, tdEmpty)),
|
|
163
|
+
),
|
|
164
|
+
action: SHORTCUT_ADD_COLUMN_BEFORE,
|
|
165
|
+
},
|
|
166
|
+
];
|
|
167
|
+
|
|
168
|
+
const case08: TestCase = [
|
|
169
|
+
'when table has no colwidth attribute and col is inserted after selection via shortcuts',
|
|
170
|
+
{
|
|
171
|
+
before: doc(
|
|
172
|
+
table({
|
|
173
|
+
localId: TABLE_LOCAL_ID,
|
|
174
|
+
})(tr(tdCursor, tdEmpty)),
|
|
175
|
+
),
|
|
176
|
+
action: SHORTCUT_ADD_COLUMN_BEFORE,
|
|
177
|
+
},
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
describe.each<TestCase>([
|
|
181
|
+
case01,
|
|
182
|
+
case02,
|
|
183
|
+
case03,
|
|
184
|
+
case04,
|
|
185
|
+
case05,
|
|
186
|
+
case06,
|
|
187
|
+
case07,
|
|
188
|
+
case08,
|
|
189
|
+
])('[case%#] %s', (_description, testCase) => {
|
|
190
|
+
it('should be able to undo/redo', () => {
|
|
191
|
+
const { editorView } = editor(testCase.before);
|
|
192
|
+
const docAtStart = clone(editorView.state.doc);
|
|
193
|
+
testCase.action(editorView);
|
|
194
|
+
expect(editorView.state.doc).not.toEqualDocument(docAtStart);
|
|
195
|
+
const docAfterAction = clone(editorView.state.doc);
|
|
196
|
+
undo(editorView.state, editorView.dispatch);
|
|
197
|
+
expect(editorView.state.doc).toEqualDocument(docAtStart);
|
|
198
|
+
redo(editorView.state, editorView.dispatch);
|
|
199
|
+
expect(editorView.state.doc).toEqualDocument(docAfterAction);
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|