@atlaskit/editor-plugin-table 0.2.6 → 1.0.1

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 (83) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/cjs/plugins/table/commands/index.js +9 -1
  3. package/dist/cjs/plugins/table/commands/referentiality.js +23 -0
  4. package/dist/cjs/plugins/table/event-handlers.js +5 -1
  5. package/dist/cjs/plugins/table/nodeviews/table.js +10 -1
  6. package/dist/cjs/plugins/table/nodeviews/tableCell.js +5 -1
  7. package/dist/cjs/plugins/table/pm-plugins/decorations/plugin.js +1 -0
  8. package/dist/cjs/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -3
  9. package/dist/cjs/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +15 -12
  10. package/dist/cjs/plugins/table/toolbar.js +78 -35
  11. package/dist/cjs/plugins/table/ui/common-styles.js +6 -3
  12. package/dist/cjs/plugins/table/ui/messages.js +17 -2
  13. package/dist/cjs/plugins/table/ui/ui-styles.js +2 -7
  14. package/dist/cjs/plugins/table/utils/decoration.js +19 -12
  15. package/dist/cjs/version.json +1 -1
  16. package/dist/es2019/plugins/table/commands/index.js +2 -1
  17. package/dist/es2019/plugins/table/commands/referentiality.js +10 -0
  18. package/dist/es2019/plugins/table/event-handlers.js +3 -1
  19. package/dist/es2019/plugins/table/nodeviews/table.js +13 -1
  20. package/dist/es2019/plugins/table/nodeviews/tableCell.js +5 -1
  21. package/dist/es2019/plugins/table/pm-plugins/decorations/plugin.js +1 -0
  22. package/dist/es2019/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -2
  23. package/dist/es2019/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +16 -11
  24. package/dist/es2019/plugins/table/toolbar.js +65 -29
  25. package/dist/es2019/plugins/table/ui/common-styles.js +15 -5
  26. package/dist/es2019/plugins/table/ui/messages.js +17 -2
  27. package/dist/es2019/plugins/table/ui/ui-styles.js +24 -16
  28. package/dist/es2019/plugins/table/utils/decoration.js +22 -13
  29. package/dist/es2019/version.json +1 -1
  30. package/dist/esm/plugins/table/commands/index.js +2 -1
  31. package/dist/esm/plugins/table/commands/referentiality.js +12 -0
  32. package/dist/esm/plugins/table/event-handlers.js +5 -1
  33. package/dist/esm/plugins/table/nodeviews/table.js +10 -1
  34. package/dist/esm/plugins/table/nodeviews/tableCell.js +5 -1
  35. package/dist/esm/plugins/table/pm-plugins/decorations/plugin.js +1 -0
  36. package/dist/esm/plugins/table/pm-plugins/decorations/utils/column-controls.js +1 -2
  37. package/dist/esm/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.js +15 -12
  38. package/dist/esm/plugins/table/toolbar.js +74 -29
  39. package/dist/esm/plugins/table/ui/common-styles.js +6 -3
  40. package/dist/esm/plugins/table/ui/messages.js +17 -2
  41. package/dist/esm/plugins/table/ui/ui-styles.js +2 -6
  42. package/dist/esm/plugins/table/utils/decoration.js +19 -12
  43. package/dist/esm/version.json +1 -1
  44. package/dist/types/plugins/table/commands/index.d.ts +1 -0
  45. package/dist/types/plugins/table/commands/referentiality.d.ts +2 -0
  46. package/dist/types/plugins/table/index.d.ts +2 -3
  47. package/dist/types/plugins/table/nodeviews/table.d.ts +4 -1
  48. package/dist/types/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.d.ts +0 -1
  49. package/dist/types/plugins/table/ui/common-styles.d.ts +4 -1
  50. package/dist/types/plugins/table/ui/messages.d.ts +15 -0
  51. package/package.json +6 -6
  52. package/report.api.md +6 -6
  53. package/src/__tests__/integration/__fixtures__/table-and-paragraph-adf.json +130 -0
  54. package/src/__tests__/integration/floating-toolbar.ts +54 -0
  55. package/src/__tests__/integration/meta-arrowup-cursor-in-first-row.ts +37 -0
  56. package/src/__tests__/unit/color-picker.ts +100 -0
  57. package/src/__tests__/unit/get-toolbar-config.ts +1 -4
  58. package/src/__tests__/unit/keymap.ts +1 -1
  59. package/src/__tests__/unit/nodeviews/cell.ts +52 -57
  60. package/src/__tests__/unit/pm-plugins/sticky-headers/tableRow.tsx +90 -8
  61. package/src/__tests__/unit/transforms/delete-columns.ts +1 -1
  62. package/src/__tests__/unit/transforms/delete-rows.ts +1 -1
  63. package/src/__tests__/unit/utils/collapse.ts +2 -2
  64. package/src/__tests__/visual-regression/__image_snapshots__/cell-options-menu-ts-table-cell-options-menu-delete-row-menu-item-should-remove-the-table-row-on-click-1-snap.png +2 -2
  65. package/src/plugins/table/commands/index.ts +1 -0
  66. package/src/plugins/table/commands/referentiality.ts +14 -0
  67. package/src/plugins/table/event-handlers.ts +7 -1
  68. package/src/plugins/table/index.tsx +6 -1
  69. package/src/plugins/table/nodeviews/table.tsx +16 -1
  70. package/src/plugins/table/nodeviews/tableCell.tsx +3 -1
  71. package/src/plugins/table/pm-plugins/decorations/plugin.ts +1 -0
  72. package/src/plugins/table/pm-plugins/decorations/utils/column-controls.ts +1 -1
  73. package/src/plugins/table/pm-plugins/sticky-headers/nodeviews/tableRow.ts +12 -10
  74. package/src/plugins/table/toolbar.tsx +84 -28
  75. package/src/plugins/table/ui/common-styles.ts +20 -4
  76. package/src/plugins/table/ui/messages.ts +18 -3
  77. package/src/plugins/table/ui/ui-styles.ts +23 -14
  78. package/src/plugins/table/utils/decoration.ts +36 -20
  79. package/dist/cjs/plugins/table/utils/referentiality.js +0 -29
  80. package/dist/es2019/plugins/table/utils/referentiality.js +0 -18
  81. package/dist/esm/plugins/table/utils/referentiality.js +0 -20
  82. package/dist/types/plugins/table/utils/referentiality.d.ts +0 -2
  83. package/src/plugins/table/utils/referentiality.ts +0 -24
@@ -34,5 +34,20 @@ declare const _default: {
34
34
  defaultMessage: string;
35
35
  description: string;
36
36
  };
37
+ confirmDeleteLinkedModalMessagePrefix: {
38
+ id: string;
39
+ defaultMessage: string;
40
+ description: string;
41
+ };
42
+ confirmModalCheckboxLabel: {
43
+ id: string;
44
+ defaultMessage: string;
45
+ description: string;
46
+ };
47
+ deleteElementTitle: {
48
+ id: string;
49
+ defaultMessage: string;
50
+ description: string;
51
+ };
37
52
  };
38
53
  export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-table",
3
- "version": "0.2.6",
3
+ "version": "1.0.1",
4
4
  "description": "Table plugin for the @atlaskit/editor",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -18,9 +18,9 @@
18
18
  "releaseModel": "scheduled"
19
19
  },
20
20
  "dependencies": {
21
- "@atlaskit/adf-schema": "^24.0.0",
22
- "@atlaskit/editor-common": "^71.0.0",
23
- "@atlaskit/editor-shared-styles": "^2.2.0",
21
+ "@atlaskit/adf-schema": "^25.0.0",
22
+ "@atlaskit/editor-common": "^72.0.0",
23
+ "@atlaskit/editor-shared-styles": "^2.3.0",
24
24
  "@atlaskit/editor-tables": "^2.2.0",
25
25
  "@atlaskit/icon": "^21.11.0",
26
26
  "@atlaskit/theme": "^12.1.0",
@@ -51,8 +51,8 @@
51
51
  "devDependencies": {
52
52
  "@atlaskit/analytics-next": "^8.3.3",
53
53
  "@atlaskit/button": "^16.5.0",
54
- "@atlaskit/editor-core": "^176.0.0",
55
- "@atlaskit/editor-test-helpers": "^17.2.0",
54
+ "@atlaskit/editor-core": "^177.0.0",
55
+ "@atlaskit/editor-test-helpers": "^18.0.0",
56
56
  "@atlaskit/link-provider": "^1.3.0",
57
57
  "@atlaskit/logo": "^13.10.0",
58
58
  "@atlaskit/media-integration-test-helpers": "^2.6.0",
package/report.api.md CHANGED
@@ -15,9 +15,9 @@
15
15
 
16
16
  ```ts
17
17
  import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
18
- import type { EditorPlugin } from '@atlaskit/editor-common/types';
19
18
  import type { EditorSelectionAPI } from '@atlaskit/editor-common/selection';
20
19
  import type { GetEditorFeatureFlags } from '@atlaskit/editor-common/types';
20
+ import type { NextEditorPlugin } from '@atlaskit/editor-common/types';
21
21
  import { TableLayout } from '@atlaskit/adf-schema';
22
22
 
23
23
  // @public (undocumented)
@@ -60,8 +60,6 @@ interface PluginConfig {
60
60
  // (undocumented)
61
61
  permittedLayouts?: PermittedLayoutsDescriptor;
62
62
  // (undocumented)
63
- stickToolbarToBottom?: boolean;
64
- // (undocumented)
65
63
  stickyHeaders?: boolean;
66
64
  // (undocumented)
67
65
  stickyHeadersOptimization?: boolean;
@@ -94,9 +92,11 @@ interface TablePluginOptions {
94
92
  }
95
93
 
96
94
  // @public (undocumented)
97
- export const tablesPlugin: (
98
- options?: TablePluginOptions | undefined,
99
- ) => EditorPlugin;
95
+ export const tablesPlugin: NextEditorPlugin<
96
+ 'table',
97
+ never,
98
+ TablePluginOptions | undefined
99
+ >;
100
100
 
101
101
  // (No @packageDocumentation comment for this package)
102
102
  ```
@@ -0,0 +1,130 @@
1
+ {
2
+ "version": 1,
3
+ "type": "doc",
4
+ "content": [
5
+ {
6
+ "type": "table",
7
+ "attrs": {
8
+ "isNumberColumnEnabled": false,
9
+ "layout": "default",
10
+ "localId": "e1365400-6226-4bb9-b3f1-b80fd3ae640a"
11
+ },
12
+ "content": [
13
+ {
14
+ "type": "tableRow",
15
+ "content": [
16
+ {
17
+ "type": "tableHeader",
18
+ "attrs": {},
19
+ "content": [
20
+ {
21
+ "type": "paragraph",
22
+ "content": []
23
+ }
24
+ ]
25
+ },
26
+ {
27
+ "type": "tableHeader",
28
+ "attrs": {},
29
+ "content": [
30
+ {
31
+ "type": "paragraph",
32
+ "content": []
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ "type": "tableHeader",
38
+ "attrs": {},
39
+ "content": [
40
+ {
41
+ "type": "paragraph",
42
+ "content": []
43
+ }
44
+ ]
45
+ }
46
+ ]
47
+ },
48
+ {
49
+ "type": "tableRow",
50
+ "content": [
51
+ {
52
+ "type": "tableCell",
53
+ "attrs": {},
54
+ "content": [
55
+ {
56
+ "type": "paragraph",
57
+ "content": []
58
+ }
59
+ ]
60
+ },
61
+ {
62
+ "type": "tableCell",
63
+ "attrs": {},
64
+ "content": [
65
+ {
66
+ "type": "paragraph",
67
+ "content": []
68
+ }
69
+ ]
70
+ },
71
+ {
72
+ "type": "tableCell",
73
+ "attrs": {},
74
+ "content": [
75
+ {
76
+ "type": "paragraph",
77
+ "content": []
78
+ }
79
+ ]
80
+ }
81
+ ]
82
+ },
83
+ {
84
+ "type": "tableRow",
85
+ "content": [
86
+ {
87
+ "type": "tableCell",
88
+ "attrs": {},
89
+ "content": [
90
+ {
91
+ "type": "paragraph",
92
+ "content": []
93
+ }
94
+ ]
95
+ },
96
+ {
97
+ "type": "tableCell",
98
+ "attrs": {},
99
+ "content": [
100
+ {
101
+ "type": "paragraph",
102
+ "content": []
103
+ }
104
+ ]
105
+ },
106
+ {
107
+ "type": "tableCell",
108
+ "attrs": {},
109
+ "content": [
110
+ {
111
+ "type": "paragraph",
112
+ "content": []
113
+ }
114
+ ]
115
+ }
116
+ ]
117
+ }
118
+ ]
119
+ },
120
+ {
121
+ "type": "paragraph",
122
+ "content": [
123
+ {
124
+ "type": "text",
125
+ "text": "text"
126
+ }
127
+ ]
128
+ }
129
+ ]
130
+ }
@@ -16,6 +16,7 @@ import {
16
16
  import { BrowserTestCase } from '@atlaskit/webdriver-runner/runner';
17
17
  import { TableCssClassName } from '../../plugins/table/types';
18
18
  import basicTable from './__fixtures__/basic-table';
19
+ import { documentWithMergedCells } from './__fixtures__/merged-rows-and-cols-document';
19
20
 
20
21
  BrowserTestCase(
21
22
  'should floating toolbar context menu sit above other context menu layers',
@@ -167,3 +168,56 @@ BrowserTestCase(
167
168
  expect(doc).toMatchCustomDocSnapshot(testName);
168
169
  },
169
170
  );
171
+
172
+ BrowserTestCase(
173
+ 'should show tooltip on hover on disabled sort button then remove it on mouse out',
174
+ { skip: ['safari'] }, // The test does not pass on CI but works on physical browser
175
+ async (client: any, testName: string) => {
176
+ const page = await goToEditorTestingWDExample(
177
+ client,
178
+ 'editor-plugin-table',
179
+ );
180
+ await mountEditor(page, {
181
+ appearance: fullpage.appearance,
182
+ allowTables: {
183
+ allowColumnSorting: true,
184
+ allowDistributeColumns: true,
185
+ allowCellOptionsInFloatingToolbar: true,
186
+ },
187
+ defaultValue: documentWithMergedCells,
188
+ });
189
+ const tableFloatingToolbarContextMenuSelector = `div[aria-label="Table floating controls"][data-editor-popup=true]`;
190
+ const sortAtoZButtonSelector =
191
+ 'div[data-role=droplistContent] div[role=presentation]';
192
+ const sortZtoAButtonSelector =
193
+ 'div[data-role=droplistContent] div[role=presentation]:nth-of-type(2)';
194
+ const tooltipSelector = 'div.atlaskit-portal div[role=tooltip]';
195
+
196
+ // Click on the cell on the table
197
+ await clickFirstCell(page);
198
+
199
+ // Table floating toolbar should appear, then hover on "Cell Options", which brings up another context menu
200
+ const cellOptionsMenuItem = await (
201
+ await page.$(tableFloatingToolbarContextMenuSelector)
202
+ ).$(`button=${tableSelectors.cellOptionsFloatingToolbarText}`);
203
+ await cellOptionsMenuItem.waitForClickable();
204
+ await cellOptionsMenuItem.click();
205
+
206
+ // No tooltip is shown
207
+ expect((await page.$$(tooltipSelector)).length).toBe(0);
208
+
209
+ // Hover Sort column A -> Z button then it should show tooltip
210
+ const sortAtoZButton = await page.$(sortAtoZButtonSelector);
211
+ await sortAtoZButton.moveTo();
212
+ const tooltip = await page.$(tooltipSelector);
213
+ await tooltip.waitForExist();
214
+ expect((await page.$$(tooltipSelector)).length).toBe(1);
215
+
216
+ // Tooltip should be removed after mouseout to next button
217
+ const sortZtoAButton = await page.$(sortZtoAButtonSelector);
218
+ await sortZtoAButton.moveTo();
219
+ await tooltip.waitUntil(async () => {
220
+ return (await page.$$(tooltipSelector)).length === 0;
221
+ });
222
+ },
223
+ );
@@ -0,0 +1,37 @@
1
+ import { BrowserTestCase } from '@atlaskit/webdriver-runner/runner';
2
+ import {
3
+ fullpage,
4
+ setProseMirrorTextSelection,
5
+ expectToMatchSelection,
6
+ } from '@atlaskit/editor-test-helpers/integration/helpers';
7
+ import {
8
+ goToEditorTestingWDExample,
9
+ mountEditor,
10
+ } from '@atlaskit/editor-test-helpers/testing-example-page';
11
+ import tableAdf from './__fixtures__/table-and-paragraph-adf.json';
12
+
13
+ BrowserTestCase(
14
+ 'meta-arrowup-cursor-in-first-row.ts: pressing command/ctrl + arrow up should move cursor into first row',
15
+ {},
16
+ async (client: any) => {
17
+ const page = await goToEditorTestingWDExample(
18
+ client,
19
+ 'editor-plugin-table',
20
+ );
21
+ await mountEditor(page, {
22
+ appearance: fullpage.appearance,
23
+ allowTables: {},
24
+ defaultValue: tableAdf,
25
+ });
26
+
27
+ await setProseMirrorTextSelection(page, { anchor: 49 });
28
+
29
+ const keys = page.isWindowsPlatform()
30
+ ? ['Control', 'Home']
31
+ : ['Meta', 'ArrowUp'];
32
+
33
+ await page.keys(keys, true);
34
+
35
+ await expectToMatchSelection(page, { type: 'text', to: 4, from: 4 });
36
+ },
37
+ );
@@ -0,0 +1,100 @@
1
+ import {
2
+ doc,
3
+ DocBuilder,
4
+ p,
5
+ table,
6
+ tdCursor,
7
+ tdEmpty,
8
+ tr,
9
+ } from '@atlaskit/editor-test-helpers/doc-builder';
10
+ import {
11
+ createProsemirrorEditorFactory,
12
+ LightEditorPlugin,
13
+ Preset,
14
+ } from '@atlaskit/editor-test-helpers/create-prosemirror-editor';
15
+ import type { EditorAnalyticsAPI } from '@atlaskit/editor-common/analytics';
16
+ import type {
17
+ FloatingToolbarButton,
18
+ FloatingToolbarItem,
19
+ GetEditorFeatureFlags,
20
+ } from '@atlaskit/editor-common/types';
21
+ import dataConsumerPlugin from '@atlaskit/editor-core/src/plugins/data-consumer';
22
+ import extensionPlugin from '@atlaskit/editor-core/src/plugins/extension';
23
+ import tablePlugin from '../../plugins/table';
24
+ import { setEditorFocus, setTableRef } from '../../plugins/table/commands';
25
+ import { getToolbarConfig } from '../../plugins/table/toolbar';
26
+
27
+ const formatMessage: (t: { id: string }) => string = (message) =>
28
+ `${message.id}`;
29
+
30
+ describe('color picker', () => {
31
+ /**
32
+ * Use `createEditorFactory` here to enable referentiality as
33
+ * `createProsemirrorEditorFactory` has some issues with correctly mimicking
34
+ * old state for the unique localId plugin
35
+ */
36
+ const createEditorFn = createProsemirrorEditorFactory();
37
+ const createEditor = (doc: DocBuilder) => {
38
+ const output = createEditorFn({
39
+ doc,
40
+
41
+ attachTo: document.body,
42
+ preset: new Preset<LightEditorPlugin>()
43
+ .add(dataConsumerPlugin)
44
+ .add(extensionPlugin)
45
+ .add(tablePlugin),
46
+ });
47
+
48
+ // Prep the table plugin state a little
49
+ const { editorView } = output;
50
+ const { dispatch } = editorView;
51
+ const tableRef = document.querySelector(
52
+ '.ProseMirror table',
53
+ ) as HTMLTableElement;
54
+ setEditorFocus(true)(output.editorView.state, dispatch);
55
+ setTableRef(tableRef)(output.editorView.state, dispatch);
56
+
57
+ return output;
58
+ };
59
+
60
+ it('should return a corect color picker option if allowBackgroundColor enabled', async () => {
61
+ const { editorView } = createEditor(
62
+ doc(p('text'), table()(tr(tdCursor, tdEmpty))),
63
+ );
64
+ const getEditorContainerWidth = () => ({ width: 500 });
65
+ const editorAnalyticsAPIFake: EditorAnalyticsAPI = {
66
+ attachAnalyticsEvent: jest.fn().mockReturnValue(() => jest.fn()),
67
+ };
68
+
69
+ // Enable tableCellOptionsInFloatingToolbar
70
+ const getEditorFeatureFlags: GetEditorFeatureFlags = jest
71
+ .fn()
72
+ .mockReturnValue({
73
+ tableCellOptionsInFloatingToolbar: true,
74
+ });
75
+
76
+ // Enable allowBackgroundColor feature flag
77
+ const { state } = editorView;
78
+ (state as any).tablePlugin$.pluginConfig.allowBackgroundColor = true;
79
+
80
+ // Create the editor
81
+ const config = getToolbarConfig(
82
+ getEditorContainerWidth,
83
+ editorAnalyticsAPIFake,
84
+ getEditorFeatureFlags,
85
+ () => editorView,
86
+ )({})(state, { formatMessage } as any, {} as any)!;
87
+
88
+ // Let's find the colorPicker from the option items list
89
+ const items =
90
+ typeof config.items === 'function'
91
+ ? config.items(state.doc.firstChild!)
92
+ : config.items;
93
+
94
+ const option = items.find(
95
+ (item: FloatingToolbarItem<any>) =>
96
+ item.type === 'select' && item.id === 'editor.table.colorPicker',
97
+ )! as FloatingToolbarButton<any>;
98
+ expect(option).not.toBeUndefined();
99
+ });
100
+ });
@@ -132,10 +132,7 @@ describe('getToolbarConfig', () => {
132
132
  );
133
133
 
134
134
  const button = getButton(editorView);
135
- expect(button.confirmDialog).toEqual({
136
- message: 'fabric.editor.tables.confirmDeleteLinkedModalMessage',
137
- okButtonLabel: 'fabric.editor.tables.confirmDeleteLinkedModalOKButton',
138
- });
135
+ expect(typeof button.confirmDialog).toBe('function');
139
136
  });
140
137
  });
141
138
  });
@@ -101,7 +101,7 @@ describe('table keymap', () => {
101
101
  .add([statusPlugin, { menuDisabled: false }])
102
102
  .add([mediaPlugin, { allowMediaSingle: true }])
103
103
  .add([analyticsPlugin, { createAnalyticsEvent }])
104
- .add([featureFlagsPlugin]);
104
+ .add([featureFlagsPlugin, {}]);
105
105
 
106
106
  const editor = (doc: DocBuilder) =>
107
107
  createEditor<TablePluginState, PluginKey>({
@@ -100,70 +100,65 @@ describe('table -> nodeviews -> tableCell.tsx', () => {
100
100
  });
101
101
  });
102
102
 
103
- describe('with tableCellOptimization on', () => {
104
- describe('nodeview update', () => {
105
- it('should not recreate nodeviews on attrs update', () => {
106
- const {
107
- editorView,
108
- refs: { pos },
109
- } = editor(
110
- doc(p('text'), table()(tr(td()(p('{pos}text')), tdEmpty, tdEmpty))),
111
- {
112
- tableCellOptimization: true,
113
- },
114
- );
115
- const { state, dispatch } = editorView;
116
- const cell = findCellClosestToPos(state.doc.resolve(pos))!;
117
- const background = tableBackgroundColorNames.get('red');
118
- const updateSpy = jest.spyOn(TableCellViews.prototype, 'update');
119
- dispatch(setCellAttrs(cell, { background })(state.tr));
120
- expect(updateSpy).toHaveReturnedWith(true);
121
- const cellDomNode = document.querySelector('td')!;
122
- expect(rgbToHex(cellDomNode.style.backgroundColor!)).toEqual(
123
- background,
124
- );
125
- });
103
+ describe('nodeview update', () => {
104
+ it('should not recreate nodeviews on attrs update', () => {
105
+ const {
106
+ editorView,
107
+ refs: { pos },
108
+ } = editor(
109
+ doc(p('text'), table()(tr(td()(p('{pos}text')), tdEmpty, tdEmpty))),
110
+ {
111
+ tableCellOptimization: true,
112
+ },
113
+ );
114
+ const { state, dispatch } = editorView;
115
+ const cell = findCellClosestToPos(state.doc.resolve(pos))!;
116
+ const background = tableBackgroundColorNames.get('red');
117
+ const updateSpy = jest.spyOn(TableCellViews.prototype, 'update');
118
+ dispatch(setCellAttrs(cell, { background })(state.tr));
119
+ expect(updateSpy).toHaveReturnedWith(true);
120
+ const cellDomNode = document.querySelector('td')!;
121
+ expect(rgbToHex(cellDomNode.style.backgroundColor!)).toEqual(background);
122
+ });
126
123
 
127
- it('preserves correct rowspan and colspan after merge cells and undo', () => {
128
- jest.spyOn(domHelpers, 'getTop').mockImplementation(() => 0);
124
+ it('should preserve the correct rowspan and colspan after merge cells and undo', () => {
125
+ jest.spyOn(domHelpers, 'getTop').mockImplementation(() => 0);
129
126
 
130
- const originalDoc = doc(
127
+ const originalDoc = doc(
128
+ table({ localId: TABLE_LOCAL_ID })(
129
+ tr(th()(p('{<cell}')), thEmpty, thEmpty),
130
+ tr(td()(p('{cell>}')), tdEmpty, tdEmpty),
131
+ tr(tdEmpty, tdEmpty, tdEmpty),
132
+ ),
133
+ );
134
+ const { editorView } = editor(originalDoc, {
135
+ stickyHeaders: true,
136
+ });
137
+ const { state, dispatch } = editorView;
138
+
139
+ dispatch(mergeCells(state.tr));
140
+ expect(editorView.state.doc).toEqualDocument(
141
+ doc(
131
142
  table({ localId: TABLE_LOCAL_ID })(
132
- tr(th()(p('{<cell}')), thEmpty, thEmpty),
133
- tr(td()(p('{cell>}')), tdEmpty, tdEmpty),
143
+ tr(th({ rowspan: 2 })(p('')), thEmpty, thEmpty),
144
+ tr(tdEmpty, tdEmpty),
134
145
  tr(tdEmpty, tdEmpty, tdEmpty),
135
146
  ),
136
- );
137
- const { editorView } = editor(originalDoc, {
138
- stickyHeaders: true,
139
- tableCellOptimization: true,
140
- });
141
- const { state, dispatch } = editorView;
147
+ ),
148
+ );
142
149
 
143
- dispatch(mergeCells(state.tr));
144
- expect(editorView.state.doc).toEqualDocument(
145
- doc(
146
- table({ localId: TABLE_LOCAL_ID })(
147
- tr(th({ rowspan: 2 })(p('')), thEmpty, thEmpty),
148
- tr(tdEmpty, tdEmpty),
149
- tr(tdEmpty, tdEmpty, tdEmpty),
150
- ),
151
- ),
152
- );
150
+ sendKeyToPm(editorView, 'Mod-z');
151
+ validateUnmergedDomCells();
152
+ expect(editorView.state.doc).toEqualDocument(originalDoc);
153
+ });
153
154
 
154
- sendKeyToPm(editorView, 'Mod-z');
155
- validateUnmergedDomCells();
156
- expect(editorView.state.doc).toEqualDocument(originalDoc);
155
+ // make sure all colspan/rowspan attributes are removed from cells
156
+ function validateUnmergedDomCells() {
157
+ const cells = document.querySelectorAll('table td, table th');
158
+ Array.from(cells).forEach((cell) => {
159
+ expect(cell.getAttribute('rowspan')).toBeFalsy();
160
+ expect(cell.getAttribute('colspan')).toBeFalsy();
157
161
  });
158
-
159
- // make sure all colspan/rowspan attributes are removed from cells
160
- function validateUnmergedDomCells() {
161
- const cells = document.querySelectorAll('table td, table th');
162
- Array.from(cells).forEach((cell) => {
163
- expect(cell.getAttribute('rowspan')).toBeFalsy();
164
- expect(cell.getAttribute('colspan')).toBeFalsy();
165
- });
166
- }
167
- });
162
+ }
168
163
  });
169
164
  });