Skip to content

Commit fb9a5ab

Browse files
committed
feat(text-editor): add tests for the table plugin
- Create tests using the new testing utilities This completes the implementation of core editor plugins and demonstrates the effectiveness of the new testing utilities.
1 parent afcdf5b commit fb9a5ab

2 files changed

Lines changed: 171 additions & 1 deletion

File tree

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import { Schema, NodeType } from 'prosemirror-model';
2+
import { Plugin } from 'prosemirror-state';
3+
import { createCustomTestSchema } from '../../test-setup/schema-builder';
4+
import { createEditorState } from '../../test-setup/editor-state-builder';
5+
import {
6+
createEditorView,
7+
createDispatchSpy,
8+
cleanupEditorView,
9+
} from '../../test-setup/editor-view-builder';
10+
import {
11+
getTableEditingPlugins,
12+
getTableNodes,
13+
createStyleAttribute,
14+
} from './table-plugin';
15+
16+
describe('Table Plugin', () => {
17+
let view;
18+
let container;
19+
20+
afterEach(() => {
21+
if (view) {
22+
cleanupEditorView(view, container);
23+
view = null;
24+
container = null;
25+
}
26+
});
27+
28+
describe('getTableEditingPlugins', () => {
29+
it('should return an array with table editing plugin when tables are enabled', () => {
30+
const plugins = getTableEditingPlugins(true);
31+
32+
expect(plugins).toBeInstanceOf(Array);
33+
expect(plugins.length).toBe(1);
34+
expect(plugins[0]).toBeInstanceOf(Plugin);
35+
});
36+
37+
it('should return an empty array when tables are disabled', () => {
38+
const plugins = getTableEditingPlugins(false);
39+
40+
expect(plugins).toBeInstanceOf(Array);
41+
expect(plugins.length).toBe(0);
42+
});
43+
44+
it('should create a working plugin that can be added to an editor state', () => {
45+
const baseSchema = createCustomTestSchema({});
46+
const tableNodes = getTableNodes();
47+
let nodes = baseSchema.spec.nodes;
48+
49+
Object.entries(tableNodes).forEach(([name, spec]) => {
50+
nodes = nodes.addToEnd(name, spec);
51+
});
52+
53+
const schema = new Schema({
54+
nodes: nodes,
55+
marks: baseSchema.spec.marks,
56+
});
57+
58+
const content = '<p>Text with table support</p>';
59+
const plugins = getTableEditingPlugins(true);
60+
const state = createEditorState(content, schema, plugins);
61+
62+
const dispatchSpy = createDispatchSpy();
63+
const result = createEditorView(state, dispatchSpy);
64+
view = result.view;
65+
container = result.container;
66+
67+
expect(plugins.length).toBe(1);
68+
expect(view.state.plugins).toContain(plugins[0]);
69+
});
70+
});
71+
72+
describe('getTableNodes', () => {
73+
it('should return an object with table node specs', () => {
74+
const tableNodes = getTableNodes();
75+
76+
expect(tableNodes).toBeDefined();
77+
expect(typeof tableNodes).toBe('object');
78+
79+
expect(tableNodes.table).toBeDefined();
80+
expect(tableNodes.table_row).toBeDefined();
81+
expect(tableNodes.table_cell).toBeDefined();
82+
expect(tableNodes.table_header).toBeDefined();
83+
});
84+
85+
it('should create node specs that can be added to a schema', () => {
86+
const baseSchema = createCustomTestSchema({});
87+
const tableNodes = getTableNodes();
88+
let nodes = baseSchema.spec.nodes;
89+
90+
Object.entries(tableNodes).forEach(([name, spec]) => {
91+
nodes = nodes.addToEnd(name, spec);
92+
});
93+
94+
const schema = new Schema({
95+
nodes: nodes,
96+
marks: baseSchema.spec.marks,
97+
});
98+
99+
expect(schema.nodes.table instanceof NodeType).toBe(true);
100+
expect(schema.nodes.table_row instanceof NodeType).toBe(true);
101+
expect(schema.nodes.table_cell instanceof NodeType).toBe(true);
102+
expect(schema.nodes.table_header instanceof NodeType).toBe(true);
103+
});
104+
105+
it('should include custom cell attributes for styling', () => {
106+
const tableNodes = getTableNodes();
107+
108+
expect(tableNodes.table_cell).toBeDefined();
109+
expect(tableNodes.table_cell.attrs).toBeDefined();
110+
expect(tableNodes.table_cell.attrs.background).toBeDefined();
111+
expect(tableNodes.table_cell.attrs.color).toBeDefined();
112+
113+
expect(tableNodes.table_cell.attrs.background.default).toBe(null);
114+
expect(tableNodes.table_cell.attrs.color.default).toBe(null);
115+
});
116+
});
117+
118+
describe('Style attribute helper', () => {
119+
it('should get style values from DOM elements', () => {
120+
const backgroundAttr = createStyleAttribute('backgroundColor');
121+
122+
const element = document.createElement('td');
123+
element.style.backgroundColor = 'red';
124+
125+
expect(backgroundAttr.getFromDOM(element)).toBe('red');
126+
});
127+
128+
it('should set style values on attributes object', () => {
129+
const backgroundAttr = createStyleAttribute('backgroundColor');
130+
const attrs: Record<string, any> = {};
131+
132+
backgroundAttr.setDOMAttr('blue', attrs);
133+
134+
expect(attrs.style).toBe('backgroundColor: blue;');
135+
});
136+
137+
it('should append to existing style attribute when setting multiple styles', () => {
138+
const backgroundAttr = createStyleAttribute('backgroundColor');
139+
const colorAttr = createStyleAttribute('color');
140+
const attrs: Record<string, any> = {};
141+
142+
backgroundAttr.setDOMAttr('blue', attrs);
143+
colorAttr.setDOMAttr('white', attrs);
144+
145+
expect(attrs.style).toBe('backgroundColor: blue;color: white;');
146+
});
147+
148+
it('should not modify the style attribute when value is falsy', () => {
149+
const backgroundAttr = createStyleAttribute('backgroundColor');
150+
const attrs: Record<string, any> = {};
151+
152+
// Test with empty string
153+
backgroundAttr.setDOMAttr('', attrs);
154+
expect(attrs.style).toBeUndefined();
155+
156+
// Test with null
157+
backgroundAttr.setDOMAttr(null, attrs);
158+
expect(attrs.style).toBeUndefined();
159+
160+
// Test with undefined
161+
backgroundAttr.setDOMAttr(undefined, attrs);
162+
expect(attrs.style).toBeUndefined();
163+
164+
// Test that existing style is preserved when falsy value is passed
165+
attrs.style = 'color: red;';
166+
backgroundAttr.setDOMAttr('', attrs);
167+
expect(attrs.style).toBe('color: red;');
168+
});
169+
});
170+
});

src/components/text-editor/prosemirror-adapter/plugins/table-plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const getTableEditingPlugins = (tablesEnabled: boolean): Plugin[] => {
99
return [];
1010
};
1111

12-
const createStyleAttribute = (cssProperty: string) => ({
12+
export const createStyleAttribute = (cssProperty: string) => ({
1313
default: null,
1414
getFromDOM: (dom: HTMLElement) => dom.style[cssProperty] || null,
1515
setDOMAttr: (value: string, attrs: Record<string, any>) => {

0 commit comments

Comments
 (0)